Discover custom ViewModels and validate Computed bindings in shared hosts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Shared Model and binding-target discovery
|
||||
|
||||
This is the first stage-4 implementation slice: a read-only binding browser shared by standalone and IntelliJ. The [DirectBinding inspector](direct-binding-inspector.md) now uses discovered targets to start editable declarations. [Converter discovery and DirectBinding validation](converter-validation.md) now extend this slice; generated metadata and the complete inspector remain subsequent work.
|
||||
This is the first stage-4 implementation slice: a read-only binding browser shared by standalone and IntelliJ. The [DirectBinding inspector](direct-binding-inspector.md) now uses discovered targets to start editable declarations. [Converter discovery and DirectBinding validation](converter-validation.md) now extend this slice; [custom ViewModel and Computed metadata](viewmodel-computed-validation.md) extend discovery further. Generated metadata and the complete inspector remain subsequent work.
|
||||
|
||||
## Use
|
||||
|
||||
@@ -12,9 +12,9 @@ For Person the browser exposes `name`, `rank`, `home`, `home.street`, and `visit
|
||||
|
||||
## Metadata boundary
|
||||
|
||||
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-v2` 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.
|
||||
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-v3` 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. This slice does not yet expose custom/replacement ViewModel members, generated metadata, Computed methods or library-provided message properties. Its compatibility results describe the Model-Attribute binding case, not the complete custom ViewModel API.
|
||||
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.
|
||||
|
||||
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. Custom ViewModel selection, 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, generated metadata precedence and complete collection compatibility remain later extensions, not silently inferred support.
|
||||
|
||||
## Qualification
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ The chooser distinguishes compatible, incompatible, unverified and invalid candi
|
||||
|
||||
The worker indexes class headers in captured classpath/module-path directories and JARs, respecting multi-release JAR selection, then loads Converter descendants without initialization. It reads annotations and method signatures without constructing Converters or invoking application methods. The index is bounded to 100,000 classes and 256 candidates; the normal worker deadline and cancellation apply. Application classes never enter a host.
|
||||
|
||||
`bindings-v2` negotiates metadata format 2, adding candidate and document-problem records to the existing BINDINGS operation without changing its wire ordinal. Older binding capabilities are not silently interpreted as this format. The UTF-8 payload, metadata counts, request identity, build identity and document-revision checks remain bounded.
|
||||
The subsequent [ViewModel/Computed slice](viewmodel-computed-validation.md) now uses `bindings-v3` and metadata format 3, adding candidate and document-problem records to the existing BINDINGS operation without changing its wire ordinal. Older binding capabilities are not silently interpreted as this format. The UTF-8 payload, metadata counts, request identity, build identity and document-revision checks remain bounded.
|
||||
|
||||
The validator covers attribute-form DirectBindings in root BindingLists: discoverable Model paths, control IDs, JavaFX property existence/writability, plain type compatibility, explicit Converter availability/capabilities and duplicate Direct/Computed targets. Known violations are errors. Unresolved types, incomplete/custom Model metadata, missing Model declarations and nested binding syntax produce warnings. Computed methods, custom/generated ViewModels, collection semantics, nested Component draft metadata, dependency injection availability and runtime method behavior are not fully validated in this slice. A warning does not certify that preview will succeed. Complete Problems-view integration and broader binding authoring remain later work.
|
||||
The validator covers attribute-form DirectBindings in root BindingLists: discoverable Model paths, control IDs, JavaFX property existence/writability, plain type compatibility, explicit Converter availability/capabilities and duplicate Direct/Computed targets. Known violations are errors. Unresolved types, incomplete/custom Model metadata, missing Model declarations and nested binding syntax produce warnings. Custom/replacement ViewModel signatures and Computed methods are now checked by the [next slice](viewmodel-computed-validation.md). Generated metadata, collection semantics, nested Component draft metadata, dependency injection availability and runtime method behavior remain incomplete. A warning does not certify that preview will succeed. Complete Problems-view integration and broader binding authoring remain later work.
|
||||
|
||||
## Automated qualification
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ A target occupied by another DirectBinding or ComputedBinding requires **Replace
|
||||
|
||||
Structural diagnostics cover duplicate targets, missing/ambiguous fx:id, empty property, malformed/missing Model path and invalid direction. [Converter discovery and binding validation](converter-validation.md) now add target-side path/property/type and capability checks, a shared chooser, and automatic validation before new previews. Saving and source repair remain available on errors.
|
||||
|
||||
Generated/custom ViewModel metadata, Computed/Repeat/Table authoring, complete semantic diagnostics and identifier rename/copy/subtree-delete reference repair remain later stage-4 work.
|
||||
[Custom ViewModel discovery and Computed validation](viewmodel-computed-validation.md) are implemented. Generated metadata, Computed/Repeat/Table authoring, complete semantic diagnostics and identifier rename/copy/subtree-delete reference repair remain later stage-4 work.
|
||||
|
||||
## Automated qualification
|
||||
|
||||
|
||||
@@ -109,3 +109,7 @@ Implemented the [read-only binding browser](binding-discovery.md) in the shared
|
||||
## Converter discovery and binding validation
|
||||
|
||||
The [next shared stage-4 slice](converter-validation.md) adds optional concrete-class capabilities, non-initializing classpath/module-path discovery, reviewed Converter proposals and DirectBinding diagnostics with preview gating in both hosts. Full metadata, structural reference repair and Problems integration remain open.
|
||||
|
||||
## Custom ViewModels and Computed bindings
|
||||
|
||||
The [shared signature-based slice](viewmodel-computed-validation.md) implements explicit Controller/Component ViewModel selection, subclass/replacement property discovery and Computed-method validation. Generated metadata, cross-View selection conflicts, full collection authoring and Problems integration remain open.
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Custom ViewModels and Computed bindings
|
||||
|
||||
The shared **Bindings → Discover targets** panel now identifies the declared Model, selected ViewModel and Controller, lists custom properties, and shows public zero-argument application methods as Computed sources. **Find Converters / Validate** and the automatic preview gate validate existing Direct and Computed declarations in both hosts. This slice validates Computed bindings edited in Source; it does not add a Computed-binding authoring form.
|
||||
|
||||
## Runtime selection and property precedence
|
||||
|
||||
Discovery reads NeitzelLib's `@ViewModelClass` on the FXML Controller. For Component `fx:root` documents it uses the captured resource path (`package/ClassName.fxml`) to identify the Component class, which is also the Controller. The worker receives this identity from the same unambiguous source-root mapping used for draft overlays. The root's actual Component class supplies its target properties, including additions beyond its FXML base type. An unavailable Component class/context is reported as unresolved; a conflicting `fx:controller` on Component FXML is an error.
|
||||
|
||||
With no explicit selection, discovery uses generic ViewModel capabilities, independent of incidental runtime reuse from another View. A subclass adds public no-argument accessors returning JavaFX `Property` to the inherited Model Attributes. Runtime precedence is preserved: reserved `latestMessage` wins, then Model Attributes, then additional property accessors. Generic nested Model paths also expose their message property. A replacement exposes only its own named JavaFX property API; it does not inherit Model Attributes, built-in message properties or dotted traversal through plain objects.
|
||||
|
||||
The selected class must be concrete and have a constructor accepting the declared Model. The most-specific compatible constructor is checked for access from NeitzelLib's module; incomparable overloads produce an ambiguity warning. No constructor or accessor runs during discovery. An overridden `ViewModel.property(String)` is dynamic: signature-derived results remain unverified and produce warnings. Raw/generic property signatures that cannot establish a value type stay unresolved. Read-only ObservableValue accessors are not advertised as bindable ViewModel properties, matching the runtime's requirement for `Property`.
|
||||
|
||||
## Computed validation
|
||||
|
||||
Discovery excludes Object methods and inherited JDK/JavaFX framework methods from the application-method inventory. Void and parameterized methods are unavailable as sources. Public inherited application methods are included. Method bodies never run during discovery.
|
||||
|
||||
Validation checks the declared Controller, public zero-argument method, reflective accessibility to NeitzelLib, target fx:id, writable JavaFX property, duplicate Direct/Computed targets and boxed return-type assignability. Private `@FXML` methods are not sufficient for NeitzelLib Computed bindings. Object or unresolved value types yield warnings; missing methods, void results and known incompatible types are errors. Existing unprefixed method names remain accepted because the runtime also accepts them; the inventory displays `#method`.
|
||||
|
||||
Computed validation still runs when a Model declaration is missing: that limits Model discovery but does not hide a known Controller-method error. Errors block new previews while saving invalid drafts and normal host Undo/Redo remain available. Results retain build/draft freshness checks. Pending target discovery can also satisfy an automatic preview-validation request, avoiding replacement of the user's discovery operation by a canvas refresh.
|
||||
|
||||
## Boundaries
|
||||
|
||||
Application classes stay in the target worker and are loaded without initialization. The `bindings-v3` capability and metadata format 3 add Controller/ViewModel identity and Computed signatures, plus the captured resource on requests. Old metadata capabilities are rejected rather than silently decoded. Existing protocol identities, payload limits, path/target limits and worker cancellation apply; the method inventory is bounded to 256 entries.
|
||||
|
||||
Generated metadata, custom BeanInfo execution, arbitrary dynamic property resolvers, full generic inference, cross-View first-use conflicts, nested ViewModel selection caused by other Views/Components, collection authoring and dependency-injection viability remain outside this slice. Method bodies, null results, constructor side effects and Computed refresh behavior are runtime concerns; compatible signatures do not prove that application code will succeed. In particular, discovery does not change which additional properties NeitzelLib observes for Computed refresh. Complete IDE Problems integration and a Computed authoring form remain later work.
|
||||
|
||||
## Automated qualification
|
||||
|
||||
Unit checks cover subclass/replacement selection, inherited properties and methods, name precedence, built-in messages, constructor mismatch, dynamic resolvers, Component resource identity/root properties, method accessibility and return types, missing Model declarations and non-initialization.
|
||||
|
||||
Real classpath and named-module fixtures check custom, replacement and Component metadata without initializing application classes. Separate fresh target processes load subclass/replacement Views through NeitzelLib, exercise custom-property write-back, confirm Model-name precedence and execute Computed methods. Shared host contracts verify resource identity through the worker transport. Live standalone and registered IntelliJ checks inspect custom properties and methods, save a type-invalid Computed binding, verify preview blocking and exact Undo/Redo, and discover replacement properties without mutating FXML. Existing rendering, Converter, input and lifecycle checks remain enabled. No manual test is required; previously skipped human checks remain skipped.
|
||||
|
||||
Qualification completed on 2026-11-13 on the pinned macOS baseline: `check-bootstrap.py` passed with **91 unit/adapter tests** (84 Maven, 7 IntelliJ), **36 fresh target processes / 484 fixture assertions**, both native standalone launch modes, both connected host adapters and **48 worker lifecycle cycles**. `check-ide-host.py` passed the registered IntelliJ editor scenarios for both classpath and module-path applications, including exclusive JavaFX 26 native-library verification and worker shutdown. No manual testing was used.
|
||||
|
||||
Local run evidence: `/tmp/viewmodel-bootstrap.log`, `/tmp/viewmodel-registered-ide.log`, `target/connected-workflow/` and `target/ide-workflow/{classpath,modulepath}.json`. Malformed-XML diagnostics are intentional recovery-test inputs. No uncaught application exception or native crash was found in these qualification runs. This is evidence for the pinned baseline, not a broader platform certification.
|
||||
Reference in New Issue
Block a user