Generate versioned Model metadata and consume it in shared binding discovery

This commit is contained in:
2026-11-13 19:08:30 +01:00
parent 9bc4569407
commit adf432b98b
20 changed files with 700 additions and 15 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ For Person the browser exposes `name`, `rank`, `home`, `home.street`, and `visit
The fresh target worker loads classes without initialization and inspects signatures. It never constructs Models, Controllers, providers, controls or Converters, never invokes getters/property accessors, and never starts JavaFX. Application types stay outside both hosts. The independently negotiated `bindings-v5` capability adds the BINDINGS operation; it uses bounded UTF-8 metadata, build/context identity and document revisions, with zero image dimensions. Existing wire operation ordinals remain unchanged.
Model fallback follows NeitzelLib's public read/write JavaBean Attribute rules and simple/complex/collection classification. Nested paths expand to depth four with cycle diagnostics; collection paths expose declared element types without pretending a collection is a single nested Model. Explicit custom BeanInfo is not executed: types requiring it report a generated-metadata diagnostic. Custom/replacement ViewModels, built-in message properties and Computed methods now follow the [signature-based selection rules](viewmodel-computed-validation.md). Generated metadata and arbitrary dynamic property APIs remain unresolved.
Model fallback follows NeitzelLib's public read/write JavaBean Attribute rules and simple/complex/collection classification. Nested paths expand to depth four with cycle diagnostics; collection paths expose declared element types without pretending a collection is a single nested Model. Explicit custom BeanInfo is not executed: types requiring it remain unverified, including when ordinary generated bean signatures exist. Custom/replacement ViewModels, built-in message properties and Computed methods now follow the [signature-based selection rules](viewmodel-computed-validation.md). Generated metadata is now supported by the [opt-in processor](generated-model-metadata.md); arbitrary dynamic property APIs remain unresolved.
Targets come from public instance JavaFX observable-property accessors. The runtime requires writable `Property` accessors, so read-only targets remain visible as incompatible. Generic observable signatures and getter types identify the value type; incomplete or contradictory signatures remain unresolved. Component `model` targets use the Component resource's explicit Model declaration instead of treating Object as a specific type. Component resource metadata comes from the selected build; current-document metadata comes from the captured draft.
@@ -24,7 +24,7 @@ Compatibility uses boxed declared types and target-runtime assignability: `view`
Discovery owns a separate workflow so it does not replace the canvas or interactive worker. It uses a leased successful build and a captured current-document overlay. Generation and document-revision checks reject obsolete replies. Document changes clear the target list and require rediscovery; Build and Refresh invalidates the panel. Explicit retained-build selection is identified in the displayed provenance. Closed editors cancel their metadata worker.
FXML parsing disables external entities and DOCTYPE. Inputs, scene-node counts, path expansion, target counts and protocol payloads are bounded. Ambiguous imports, duplicate IDs, missing classes, invalid XML and absent declarations produce diagnostics. Attached-property binding discovery, open child-draft metadata overlays, generated metadata precedence and complete collection compatibility remain later extensions, not silently inferred support.
FXML parsing disables external entities and DOCTYPE. Inputs, scene-node counts, path expansion, target counts and protocol payloads are bounded. Ambiguous imports, duplicate IDs, missing classes, invalid XML and absent declarations produce diagnostics. Attached-property binding discovery, open child-draft metadata overlays, broader custom metadata and complete collection compatibility remain later extensions, not silently inferred support.
## Qualification
+52
View File
@@ -0,0 +1,52 @@
# Generated Model metadata for discovery and authoring
Applications can now opt into the separate `designer-model-processor` annotation processor. It emits versioned Model property descriptions during compilation, without loading or executing application classes. Both hosts consume those descriptions through the same isolated target discovery worker. The shared browser identifies **Generated Model metadata 1.0** or **Compiled Model signatures** in its provenance. Direct bindings, nested paths, Repeat collections and Table discovery use the same resulting Attribute description.
## Application setup
Configure the application module's Maven compiler plugin (3.14.1 in the qualified fixtures):
```xml
<configuration>
<annotationProcessorPaths>
<path>
<groupId>de.neitzel.fxdesigner</groupId>
<artifactId>designer-model-processor</artifactId>
<version>0.1.0-SNAPSHOT</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Adesigner.models=com.example.Person,com.example.Address</arg>
</compilerArgs>
</configuration>
```
Keep the selection in the checked-in POM. Merge this configuration with any existing annotation processor paths and compiler arguments. No Model annotation, runtime dependency, FXML rewrite, or host-specific configuration is needed. The explicit FXML `neitzel-model` processing instruction remains authoritative for each View. A missing selected type fails compilation. An empty selection generates nothing. Only Models belonging to the current compilation source set are emitted; test compilations and dependent modules do not duplicate resources for already compiled Models.
The processor emits public read/write JavaBean signatures for selected types and nested bean types, with inherited members, boolean `is` precedence and declared collection element types. Read-only properties and the runtime's reserved `latestMessage` are excluded from the generated property list. Target discovery supplies built-in properties and applies the existing simple/complex/collection rules, path depth/cycle limits, ViewModel selection and direction-aware compatibility. Metadata does not initialize Models, call accessors, construct Controllers, or run custom BeanInfo.
## Format and integrity
Each Model has one UTF-8 resource at `META-INF/neitzel-fx-designer/models/<binary-class-name>.properties` in the class output and packaged application JAR. Schema `1.0` contains the Model identity and an ordered list of names, binary value types, declared collection element types, readers and writers. Output is deterministic and contains no timestamp or machine paths. The shared `ModelMetadata` contract bounds input size to 256 KiB and property count to 256; unknown versions and invalid structures are rejected.
Target discovery prefers generated descriptions and verifies the complete eligible property inventory and signatures against the captured compiled type. This integrity check uses non-initializing reflection, not application execution. No claim of reflection-free discovery or improved performance is made. Absent metadata uses the existing compiled-signature fallback. Present but malformed, duplicate, incompatible or stale metadata is an error, with no silent fallback; normal invalid-draft saving remains available and existing validation gates block new previews. Custom BeanInfo semantics remain unverified and are not silently replaced by generated ordinary-bean signatures. Unsupported generic signatures remain subject to conservative validation rather than guessed types.
Build and Refresh already performs `clean package` in an isolated reactor copy. It captures generated resources with the same immutable outputs and dependency identities used for preview. Changed Models or selection settings invalidate the build input identity. Clean rebuilds remove obsolete properties and deselected metadata; callers building outside the designer must also use a clean build after removals or selection changes. Arbitrary incremental javac output cleanup is not implemented. A failed build cannot activate partial metadata, and explicit last-successful-build use keeps its earlier metadata and outdated label.
## Boundaries and validation
This is build-time Model metadata for existing discovery and binding authoring. It does not generate Java ViewModel subclasses, a ViewModel registry, editable FXML forms, labels/control defaults, arbitrary BeanInfo metadata, Java source origins or project-wide Model selection UI. Those retain their later roadmap gates. The processor is a Java 21 build artifact depending only on the contracts; it is not packaged in either host or required on the application runtime path. Wire DTOs and protocol versions do not change.
Automated tests compile real source with the processor, verify deterministic inherited/collection signatures and non-execution, clean-build removal, missing selections, schema bounds, generated/fallback equivalence, stale signatures and duplicate resources. Real classpath and module-path fixture processes require generated Person and nested Address metadata and retain their non-initialization assertions. The live shared-host scenario requires generated metadata provenance before handing discovery to the binding inspector, then runs existing source-preserving binding authoring and Undo/Redo tests in standalone and registered IntelliJ. No manual testing is requested; earlier skipped manual checks remain skipped.
Run the bootstrap and registered IntelliJ qualification commands in the [README](../README.md).
### Qualification — 2026-11-13
The clean shared build passes 135 Maven tests and ten IntelliJ adapter tests. The real Java 21 fixtures pass 36 target processes with 518 checks, including generated Person/Address resource use in both launch modes and non-initialization assertions. Native standalone classpath and module-path scenarios pass generated discovery, existing Direct/Computed/Repeat/Table authoring, source-preserving edits and Undo/Redo. The lifecycle suite retains its 48-cycle and abrupt-owner-death checks.
The first fixture integration exposed duplicate resources from Maven test compilation inheriting the processor configuration. Restricting emission to the current compilation's source types fixed this; a dependent-compilation regression now verifies that compiled Models are not emitted twice. Generated output remains part of the normal immutable snapshot and packaged module resources.
The full bootstrap passed, including Java 21 bytecode/linkage, plugin packaging exclusions and documentation checks. Registered IntelliJ classpath qualification also passed generated discovery, source-preserving authoring, native diagnostics/Undo/Redo, exclusive JavaFX 26 natives and worker shutdown. The first registered module-path attempt passed generated discovery but timed out at the existing Table preview-gating assertion; it is retained as reliability evidence. An unchanged module-path-only rerun of the registered qualification harness passed all assertions, exclusive JavaFX 26 native checks and worker shutdown (`/tmp/model-metadata-ide-modulepath-retry.log`). The startup/persistence/preview-gate reliability follow-up remains open; no assertion was weakened. No manual testing was used.
Local evidence: `/tmp/model-metadata-bootstrap2.log`, `/tmp/model-metadata-registered-ide.log`, `designer-target-tools/target/preview-fixtures/`, `target/connected-workflow/` and `target/ide-workflow/`. Earlier development evidence is retained in `/tmp/model-metadata-build.log`, `/tmp/model-metadata-build2.log` and `/tmp/model-metadata-bootstrap.log`. Generated qualification artifacts are not repository inputs.
+1
View File
@@ -27,6 +27,7 @@ The artifact names below are established by work package 3. See [implemented bou
| `designer-intellij` | FXML editor, IDE Documents/commands, project/build/navigation integration and focus | Adapts the same core/UI; qualify build and packaging against the selected IDE SDK |
| `designer-preview-api` | Typed example descriptors and fresh preview-session lifecycle | Small project-facing artifact; no Kit or IntelliJ dependency |
| `designer-target-tools` | Discovery and NeitzelLib loading/rendering adapter in the application runtime | Uses contracts/preview API and target-compatible library dependencies; never execute application classes in a host |
| `designer-model-processor` | Opt-in build-time Model signature resources | Contracts only; no application execution or host dependency |
| `designer-maven-plugin` | Effective project/dependency/runtime capture in the selected Maven build JVM | No Kit/IntelliJ or target application runtime dependency |
| `integration-fixtures/` | Real classpath and module-path Maven applications, examples and failure cases | Same scenarios consumed by both hosts; normal artifact dependencies |
+4
View File
@@ -145,3 +145,7 @@ The [shared diagnostics slice](shared-diagnostics.md) adds a View-wide Problems
## Source highlighting and diagnostic quick fixes
The [shared highlighting/fixes slice](source-highlighting-fixes.md) adds current source underlines, explicit direction corrections and conservative declaration removal. Both hosts apply lexical edits through their authoritative Undo/Redo transaction. IntelliJ adds native XML annotations and Alt+Enter actions, with revision and publication guards. Generated metadata, richer Java/Column/Row origins, further semantic fixes and project-wide diagnostics remain open.
## Generated Model metadata
The [generated Model metadata slice](generated-model-metadata.md) adds an opt-in compiler processor, versioned deterministic resources, generated-first target discovery with signature integrity checks, and shared provenance in both hosts. Existing binding authoring consumes the resulting Attributes without host-specific logic or new undo paths. Missing metadata retains compiled fallback; invalid present metadata is diagnosed. Java ViewModel/registry and FXML form generation, custom BeanInfo semantics and broader source origins remain later work.