Skip to content

2.0.0 beta 1 fixes and enhancements#157

Merged
fuzzzerd merged 32 commits into
masterfrom
plugin-enhancements
Apr 16, 2026
Merged

2.0.0 beta 1 fixes and enhancements#157
fuzzzerd merged 32 commits into
masterfrom
plugin-enhancements

Conversation

@fuzzzerd
Copy link
Copy Markdown
Owner

@fuzzzerd fuzzzerd commented Apr 16, 2026

Summary

Beta 1 round of fixes and enhancements focused on a strongly-typed scripting model, a leaner plugin contract, and editor UX.

Typed POCO script steps

  • ScriptStep is now abstract; each known FileMaker step has a dedicated POCO subclass that owns its own XML/display/validation contract:
    • GoToLayoutStep, GoToRecordStep, PerformScriptStep
    • SetFieldStep, SetVariableStep
    • ShowCustomDialogStep (with ShowCustomDialogButton / ShowCustomDialogInputField)
    • CommentStep, control-flow steps (If/Else If/Else/End If, Loop/Exit Loop If/End Loop)
    • RawStep + RawStepAllowList as the escape hatch for unknown/verbatim XML
  • Typed value objects back the step POCOs: FieldRef, Calculation, LayoutTarget, NamedRef, Animation, PerformScriptTarget.
  • POCOs round-trip verbatim FileMaker XML via SourceXml preservation; each has its own test suite.

Domain model

  • Extract SharpFM.Model package as the single source of truth for clip/script/schema types; plugins consume it directly.
  • Move Apply* operations onto FmScript/FmTable; migrate FmTable.Fields to ObservableCollection.

Scripting & serialization

  • Replace the StepHandler/StepParamValue pipeline with stateless catalog helpers (CatalogXmlBuilder, CatalogParamExtractor, CatalogDisplayRenderer, CatalogValidator, StepXmlFactory, StepDisplayFactory).
  • Wholesale XML replacement driven by a single source of truth.
  • Multi-line statement handling (MultiLineStatementRanges, continuation indent/renderer) in the script editor.

Plugin system

  • Simplify IPluginHost: drop redundant read/update methods and RefreshSelectedClip; expose domain-level operations.
  • Target .NET 10; add ClipData extensions used by MCP read paths.

Editor UX

  • Sealed-step renderers: cog generator, italic colorizer, squiggle renderer, read-only provider, selection check, bounds-checked anchor offsets.
  • Monaco-style snippet completion, bracket-boundary-aware provider, debounce unified via DebouncedEventRaiser.
  • New RawClipboardWindow and RawStepEditorWindow diagnostics; transient status messages from MainWindowViewModel.

Tests

  • Verbatim FileMaker XML fixtures for lossless round-trip.
  • New suites for every typed step POCO, value type, catalog helper, sealed-step preservation, multi-line ranges, continuation indent, and script metadata.
  • Remove obsolete handler/StepParamValue tests alongside the code they covered.

fuzzzerd added 30 commits April 4, 2026 23:33
Expand IPluginHost with by-name clip access (GetClip, UpdateClipXml,
CreateClip, RemoveClip) and domain-level operations for scripts
(GetScriptSteps, UpdateScriptSteps) and tables (GetTableFields,
UpdateTableFields). These work directly on the FmScript/FmTable models,
bypassing display text parsing for reliable mutations.

Additional changes:
- Upgrade all projects to .NET 10
- Add PluginLoadContext with directory probing for plugin dependencies
- Support plugin subdirectories (plugins/{name}/{name}.dll)
- Add ILogger support via IPluginHost.CreateLogger
- PluginHost marshals all mutations to UI thread (EnsureUiThread)
- Dispose plugins on app exit for clean shutdown
- Fix TableClipEditor crash on duplicate field IDs
- Fix ShowCustomDialog positional param parsing
- Notify UI on external clip updates (SyncEditorFromXml)
…eplacement

ParamValues is now the sole source of truth for script step serialization.
Remove SourceXml from ToXml() and ToDisplayLine() paths — generic
ParamValues-based serialization handles all param types including complex.

- Remove ToDisplayLine and ToXml from IStepHandler and all 8 handlers
- Remove SyncEditorFromXml and SyncModelFromEditor from ClipViewModel
- Add ReplaceEditor(xml) for wholesale editor replacement on external updates
- Remove SyncToModel from TableEditorViewModel
- Remove PatchViewModel diff/patch logic from TableClipEditor
- Add complex param support (Buttons, InputFields, SortList, etc.)
- Add step catalog lookup (GetAvailableSteps, GetStepDefinition)
- PluginHost delegates to ReplaceEditor for all XML writes

Net -285 lines removed.
Introduce test fixtures built from real FileMaker clipboard XML to drive
the script-step domain model toward lossless ingestion and emission.
These tests express the contract the new typed step POCOs must satisfy:
every attribute and nested element present in the source XML survives
the round-trip through the domain model unchanged.

The display format extends with a (#id) suffix to carry named-ref ids
losslessly through the editor text, which generic catalog-driven
rendering cannot represent. Expected to fail until the typed domain
model replaces the current string-bag param pipeline.
Add the foundational value types that replace the stringly-typed
StepParamValue.Value slot with lossless, strongly-typed representations:

  NamedRef      id+name pair for Layout/Script/TableOccurrence refs
  FieldRef      table+id+name or variable form for field references
  Calculation   CDATA-wrapped calc expressions with configurable wrapper
  LayoutTarget  closed discriminated union of Go to Layout destinations
  Animation     raw wire-string record allowing unknown values to pass through

These types have no dependency on ScriptStep or StepParamValue and serve
as the stable building blocks for the per-step POCO hierarchy that will
replace the generic param bag. Each type owns its XML mapping and is
covered by focused unit tests asserting round-trip preservation.
…zation

Add CatalogParamExtractor, CatalogDisplayRenderer, CatalogValidator, and
CatalogXmlBuilder as pure functions over (XElement, StepDefinition) pairs.
These helpers replace the behavior the soon-to-be-removed StepParamValue
wrapper provided, but without the intermediate per-param object.

CatalogParamExtractor centralizes the dispatch on StepParam.Type and the
Extract* helpers ported verbatim from StepParamValue.FromXml.

CatalogDisplayRenderer reproduces the generic ToDisplayLine path and
the StepParamValue.ToDisplayString / FormatComplexForDisplay output,
including the comment step's special "# text" shape.

CatalogValidator ports the per-param validation rules (enum/label
membership, field/variable syntax check) into a stateless call.

CatalogXmlBuilder ports the per-type Build* helpers plus the display-
token positional/label matcher into a single stateless BuildStep path,
adds a param-map entry point for MCP operations, and an UpdateParam
helper for single-param mutations. The historical id="0" hardcode for
named-ref types is dropped — typed step POCOs will carry real ids on
their own, and display-text-originated refs simply omit the id attribute.

The helpers are internal, with InternalsVisibleTo SharpFM.Tests so their
behavior can be validated in isolation. 20 unit tests cover the major
code paths; verbatim FM-XML end-to-end coverage follows when typed POCOs
consume these helpers.
ScriptStep becomes an abstract base with two concrete strategies: typed
step POCOs (one per migrated FileMaker step) and a transitional RawStep
that wraps a verbatim source element for any step that does not yet
have a typed implementation. StepXmlFactory and StepDisplayFactory
route parsed XML and display text to typed POCOs when registered and
fall back to RawStep otherwise.

Delete StepParamValue, every handler file, and the
SpecializedDisplayRenderer hook. Handlers existed only to special-case
reading and writing through the generic ParamValues bag; with the bag
gone and typed POCOs owning their own serialization, the handler
interface has nothing left to abstract over.

Rewrite FmScript.ApplyAdd/ApplyUpdate to build and mutate step
elements through CatalogXmlBuilder. ScriptTextParser's
MatchDisplayParams moves into CatalogXmlBuilder and the parser
dispatches through the new factories, with a fall through to
CatalogXmlBuilder.BuildStep wrapped in a RawStep for catalog-known
steps without a typed POCO.

Fix a pre-existing CatalogXmlBuilder bug exposed during the port:
Show Custom Dialog has two namedCalc params (Title, Message) that
share xmlElement="Calculation" and differ only in wrapperElement.
The old dictionary-keyed build path silently overwrote Title with
Message. Switch the internal representation to a positional list so
distinct slots stay independent.

Update ComplexParamTests and ScriptStepTests.UnknownStep to exercise
the new lossless RawStep behavior. Delete StepParamValueTests.cs and
HandlerTests.cs; the verbatim Go to Layout fixtures move to a new
GoToLayoutStepTests.cs that anchors the upcoming typed POCO.
Introduce the first typed script step. GoToLayoutStep carries a
LayoutTarget discriminated union (Original / Named / ByNameCalc /
ByNumberCalc) and an optional Animation record, and owns its own
FromXml, ToXml, ToDisplayLine, and FromDisplayParams. A module
initializer registers its factory delegates with StepXmlFactory and
StepDisplayFactory so ScriptStep.FromXml and ScriptTextParser dispatch
to the typed path before falling through to RawStep.

Named layouts render with a (#id) suffix (e.g. "Projects" (#81)) so
the display editor can round-trip the layout id losslessly. The
by-calculation variants emit a nested <Layout><Calculation> shape
matching what FileMaker Pro actually writes. Animation is preserved
verbatim via its wire string, with null meaning "no Animation element
in the source".

FromXml accepts both FM Pro's real wire values (LayoutNameByCalc,
LayoutNumberByCalc) and the legacy long forms (LayoutNameByCalculation,
LayoutNumberByCalculation) as aliases for tolerance against older
stored XML. ToXml always emits the short form.
- Implemented GoToRecordStep to represent the "Go to Record/Request/Page" script step, including XML serialization and display formatting.
- Added PerformScriptStep for the "Perform Script" step, supporting both reference and calculation targets.
- Created SetFieldStep for the "Set Field" script step, handling field references and calculations.
- Introduced SetVariableStep for the "Set Variable" script step, managing variable names, values, and repetitions.
- Developed ShowCustomDialogStep to represent the "Show Custom Dialog" step, including button and input field configurations.
- Added supporting classes for PerformScriptTarget, ShowCustomDialogButton, and ShowCustomDialogInputField to encapsulate related data.
- Enhanced MainWindow and ViewModel to support new clipboard operations for copying scripts and script steps.
- Introduced MultiLineStatementRanges to compute line ranges for logical script steps.
- Enhanced FmScript to support indentation and rendering of multi-line calculations.
- Added ContinuationIndentStrategy for auto-indenting new lines within multi-line steps.
- Created ContinuationLineRenderer to visually link continuation lines in the editor.
- Developed StepIndexMargin to display step indices in a FileMaker-style format.
- Updated ScriptValidator to correctly handle continuation lines without flagging them as separate steps.
- Added tests for multi-line calculations and their round-trip parsing to ensure correctness.
…nt status updates

test: Add LoopCommentHighlightRepro to verify multi-line comment highlighting behavior

test: Update MultiLineStatementRangesTests to reflect blank lines as empty comment steps

test: Update ScriptStepTests to include field ID in display output

test: Implement SealedSelectionCheckTests for validating sealed step selections

test: Add SealedStepPreservationTests to ensure sealed steps maintain XML state across edits

test: Add FieldParamCatalogRoundTripTests for validating field parameter serialization

test: Implement CommentStepTests to validate comment step display and round-trip behavior

test: Add RawStepAllowListTests to ensure raw steps are correctly managed in the allow list

test: Update SetFieldStepTests to include field ID in display output

test: Enhance FieldRefTests to validate ID preservation in display tokens
PR #155 introduced a save/dirty editor model and FmScript mutation
helpers on master. Both are superseded on this branch by typed POCO
steps, the sealed-step anchor cache, and FmScript.Apply for MCP. Merge
taken with no content from master.
@github-actions
Copy link
Copy Markdown

Test Results

✔️ Tests 514 / 514 - passed in 6.2s
✔️ Coverage 73.71% - passed with 70% threshold
📏 3076 / 3881 lines covered 🌿 1502 / 2330 branches covered
🔍 click here for more details

✏️ updated for commit 438fa38

@fuzzzerd fuzzzerd merged commit 5ab4f3a into master Apr 16, 2026
6 checks passed
@fuzzzerd fuzzzerd deleted the plugin-enhancements branch April 16, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant