Aprillz.MewUI.Analyzers #169
al6uiz
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Roslyn analyzers and refactorings for MewUI fluent markup. Ships as a NuGet analyzer (
analyzers/dotnet/cs), so it works in Visual Studio, VS Code (C# Dev Kit), Rider, and CI from one reference.Build-time only: nothing ships into the runtime / NativeAOT output.
Aprillz.MewUI.Analyzersnetstandard2.0, Roslyn pinned to 4.8 for broad host compatibility.Status
MEW1101InitializerToFluentAnalyzer.cs,InitializerToFluentCodeFix.csMEW1102FluentChainFormatRefactoring.csMEW1103MergeChainStatementsRefactoring.csMEW1104AssignmentToFluentCallRefactoring.csShared pieces:
FluentMethodResolver.csresolves a property/event name to its fluent setter extension. Theextension methods are the source of truth (no mapping table to drift); it also tries the
On-prefixed name (Click->OnClick).FluentChainLayout.csis the shared layout engine (used by MEW1101 / MEW1102 / MEW1103): itrebuilds a chain from its structure, expands element children as a tree, keeps values inline, and
re-indents multi-line lambda bodies.
20 tests in
tests/MewUI.Analyzers.Testcover all four.MEW1101- Convert object initializer to fluent chainRewrites an object initializer into the equivalent MewUI fluent setter chain (and expands it).
Severity is
Hidden(no squiggle, lightbulb only). Raise it via.editorconfigif you want itvisible:
dotnet_diagnostic.MEW1101.severity = suggestion.Rules
Trigger. An object creation with an object initializer where at least one member
Name = valuemaps to a fluent setter.
Fluent setter. An in-scope extension method named exactly
Name(orOn+Namefor events),callable on the created type, taking a single parameter that
valueconverts to. The extensionmethods are the source of truth - any setter you add is picked up automatically.
Conversion. Each matching member becomes
.Name(value)in source order;new T { ... }gainsan explicit
(). Two or more converted members are expanded onto separate lines.Events. A delegate-typed property
Click = handlermaps to.OnClick(handler)via theOn-prefix rule.Partial conversion. Members with no matching setter stay in a residual initializer.
No diagnostic when no member maps to a setter.
Not yet handled
Children = { a, b }->.Children(a, b).MEW1102- Fluent chain expand / collapseA one-shot refactoring (Ctrl+.), not a format-on-save hook (format-on-save calls the host's built-in
formatter, never a refactoring). Both actions are always offered, so "Expand" also re-formats an
already-expanded chain in place.
Rules
Trigger. Caret inside a member-access invocation chain (one or more calls).
Expand. Each chained
.Method(...)moves to its own line, indented one level under the linethe chain starts on.
Element children. When an argument is itself an element chain, the argument list breaks and
each element is expanded as its own tree, separated by a blank line:
An element chain is one rooted in
new X(), a call (Factory()), or a value (a local / field).A chain rooted in a type (a static factory such as
Color.FromRgb(...)) is a value and staysinline (it is not split). This needs semantics, so MEW1102 uses the semantic model; MEW1101 /
MEW1103 format synthesized chains and fall back to a name heuristic (types are PascalCase).
Lambda blocks. A multi-line lambda body is re-indented so it aligns with its new position:
Collapse. The inverse: the whole chain, including nested element children, is joined back onto
one line.
Idempotent. Each run rebuilds the chain from its structure, so repeated runs are stable.
Not yet handled
.editorconfig.MEW1103- Merge statements into a fluent chainFolds a
var x = ...;/x = ...;statement and the consecutive statements that configurexintoa single chain. Caret on the anchor statement.
Rules
Anchor. A single local declaration (
var x = ...) or a simple assignment (x = ...).Follow-ups. Consecutive statements that are either
x.Method(...);(a fluent call) orx.Event += handler;(an event subscription, folded in as.OnEvent(handler)). Each must returnx's own type, so chaining and assigning back toxstay valid; the first non-matching statementstops collection.
.Ref(out var x). For a local declaration of a reference type, the reference is capturedinline with
.Ref(out var x)(the MewUI idiom) instead of keeping avar x = ...;statement,when a
Refextension exists. Field / property assignments keepx = chain;.The merged chain is expanded via the shared layout engine.
MEW1104- Property assignment to fluent callConverts
receiver.Prop = value;intoreceiver.Prop(value);when a fluent setter forPropexistson the receiver's type. Caret on the assignment.
Not offered when no fluent setter resolves for the assigned member.
Testing
tests/MewUI.Analyzers.TestusesMicrosoft.CodeAnalysis.CSharp.CodeFix.Testingand.CodeRefactoring.Testing. Tests define small self-contained fluent APIs in the test source, soresolution runs without the MewUI build.
Beta Was this translation helpful? Give feedback.
All reactions