Discover Converter capabilities and validate shared binding drafts

This commit is contained in:
2026-11-13 12:58:08 +01:00
parent 17b1bce704
commit 5a208d2336
35 changed files with 1096 additions and 34 deletions
+38
View File
@@ -0,0 +1,38 @@
# Converter discovery and binding validation
Both hosts use the same **Bindings → Direct bindings → Find Converters / Validate** action. It checks the current document and lists Converter candidates for the form's Model path, target property and direction. Choose a candidate or keep an explicit class name, review the form, then **Apply binding**. Discovery and validation never edit FXML. Apply uses the existing source-preserving command and host Undo/Redo.
A single compatible candidate is proposed only when the Converter field is empty. Multiple matches require a choice. Explicit selections, including unannotated classes, are retained. Form changes reject obsolete suggestions; document changes and builds invalidate validation. Results identify the draft revision and explicitly retained builds. Validation uses a separate target worker and leaves existing interactive sessions alone. New preview requests validate the current parent document before launching; known errors block the request, while warnings remain visible and saving stays available.
## Optional capabilities
The application-facing `designer-preview-api` artifact supplies a runtime-retained annotation with no JavaFX, Kit or IntelliJ dependency:
```java
@ConverterCapabilities(modelType = Integer.class,
controlType = String.class,
reverse = true)
public class RankConverter implements de.neitzel.fx.view.Converter {
// Implement toControlValue and toAttributeValue.
}
```
Import `de.neitzel.fxdesigner.preview.ConverterCapabilities`. Named modules using this annotation require `de.neitzel.fxdesigner.preview`. The annotation is tooling metadata; NeitzelLib's Converter interface and runtime behavior remain unchanged. No new NeitzelLib artifact is required.
Metadata must be declared on the concrete class. An unannotated subclass does not inherit verified capabilities. Forward conversion is always required, including initialization of a converted `model` binding. `model` and `both` additionally require reverse conversion. Declaring reverse support while inheriting the interface's default throwing method is an error. Declared input/output types are checked with boxing and target-runtime assignability in each required direction. Plain bindings retain NeitzelLib's separate direction rules. NeitzelLib bypasses Converters for complex and collection Attributes; those paths get no proposals, and an explicit Converter produces a warning rather than a false compatibility claim.
The chooser distinguishes compatible, incompatible, unverified and invalid candidates. Metadata is a declared contract, not a proof of implementation behavior. Unannotated Converters remain usable with a warning. Target previews still exercise conversion, and the real fixtures test conversion failure/value preservation and recovery through NeitzelLib's Message behavior.
## Worker and validation boundary
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 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.
## Automated qualification
Unit tests cover non-initialization, inherited/unannotated metadata, reverse-method inconsistencies, assignability, the special converted model-direction initialization rule, path/property errors and metadata round trips. Real classpath and named-module fixtures exercise discovery and validate the same application declarations without initializing Converters. Shared live-UI checks cover explicit preservation, a unique proposal requiring Apply, ambiguous matches requiring selection, unverified warnings, type-error preview blocking and source-preserving Undo/Redo in standalone and registered IntelliJ. Existing rendering, input and worker lifecycle checks remain enabled. No manual review is required for this slice; earlier skipped manual checks retain their recorded disposition.
Qualification on 2026-11-13 passed: 79 Maven tests and 7 IntelliJ adapter tests; 34 target processes with 438 fixture assertions; 48 worker lifecycle cycles; connected workflows and live shared UI in standalone and registered IntelliJ for classpath and module-path applications. Native isolation, worker shutdown, bytecode/package boundaries and documentation checks passed. Final host logs contain no uncaught exceptions and no new native crash report appeared. The live regression exposed and fixed an automatic canvas-refresh race that replaced an in-flight chooser request; pending validation now also satisfies that preview request. Local evidence: `/tmp/converter-bootstrap.log`, `/tmp/converter-registered-ide.log`, and `/tmp/converter-protocol-test.log` (including rejection of the old binding capability).