Skip to content

feat: make IgniteUI.Blazor.Lite trim-compatible - #359

Open
damyanpetev wants to merge 8 commits into
masterfrom
dpetev/trimmable
Open

feat: make IgniteUI.Blazor.Lite trim-compatible#359
damyanpetev wants to merge 8 commits into
masterfrom
dpetev/trimmable

Conversation

@damyanpetev

@damyanpetev damyanpetev commented Aug 21, 2026

Copy link
Copy Markdown
Member

Closes #348

What & why

Enabling <IsTrimmable>true</IsTrimmable> surfaced 48 unique trim-analysis warnings per TFM (net8/net9/net10), concentrated in the JSON interop layer and the reflective data-source/module plumbing. This PR resolves all of them — real fixes where possible, narrowly-justified suppressions only where the reflected members are provably preserved (framework/library reflection) or belong to app-supplied data types with a documented preservation requirement — so the library is safe to consume from apps published with trimming (the Blazor WebAssembly publish default).

Based on dpetev/event-callback-compare-fix: its EventCallbackExtensions.EqualsCompat replaces the old reflective CompareEventCallbacks and is already trim-clean under the new analyzer gate with no annotations (typeof(EventCallback<TValue>).GetField is statically analyzable).

Changes

Real fixes

  • JSON source generation (docs): new IgbJsonContext (src/componentsBase/IgbJsonContext.cs) covers the closed set of wire shapes (Dictionary<string,object>, its array, object, object[], string, string[], int[], double[]); all ~25 JsonSerializer call sites in BaseRendererControl now use typed JsonTypeInfo overloads — the IL2026s are gone for real, not suppressed. Deserialized object values still surface as JsonElement, identical to the reflection-based behavior.
  • DateRangePicker Change handler: the Serialize(args.Detail) → Deserialize<IgbDateRangeValue> round-trip (with a per-event JsonSerializerOptions allocation) is replaced by a direct Start/End copy — the two types share the exact shape.
  • Trim-safe module registration, zero API changes to registration itself: new IIgbModule interface (static abstract Register) implemented by all 75 *Module classes, each also carrying a self-referencing [IgbModule<TSelf>] whose [DynamicallyAccessedMembers(PublicMethods)] generic parameter makes the trimmer preserve the module's Register whenever the type itself is kept — custom attributes live and die with their type, so this works for typeof args, arrays, and runtime-computed Types alike, while unreferenced modules still trim fully (verified empirically: preloading an otherwise-unreferenced module through the untouched params Type[] overload silently no-ops without the attribute, works with it; a drift-guard test asserts every module's attribute references itself). Alternative designs were built and verified, then dropped: an IgbModuleRef implicit-conversion wrapper and [OverloadResolutionPriority] dual overloads (call-site tracing can't cover arrays/computed Types; the wrapper broke Type[] array call sites) and a fluent Add<T>() collection builder (reflection-free but API shape not wanted — kept as a possible future addition).

Annotations (DynamicallyAccessedMembers)

  • BaseRendererControl class: PublicProperties — inherited by every component, satisfies the BuildSequenceInfo property walk; costs nothing real since rendered components already get All via OpenComponent<T>.
  • Utils.TryGetWCEnumName / ObjectToParam(…, Type, …) chain: deliberately unannotated — DAM on method parameters of component base classes surfaces IL2111 in every consuming app (see suppression table); enum origins are typeof literals or boxed library enum fields at every call site.
  • IgbComponentRendererContainer.ComponentType (property only; the backing field is deliberately unannotated — field DAM surfaces IL2110, see suppression table) and DynamicContentInfo.ControlType / TypedDynamicContent(Type): All, as required by RenderTreeBuilder.OpenComponent(Type).
  • UnmarshalledDataSource.GetIListTypeArg/GetIEnumerableTypeArg: Interfaces.

Suppression inventory (each [UnconditionalSuppressMessage], with justification)

Site Code Why it is safe
BaseRendererControl.SendJsonSync IL2026 Arguments are strings, DotNetObjectReference<WebCallback> (a library type; only its id is serialized), ElementReference[]; the return is consumed as JsonElement and re-parsed only via the source-generated IgbJsonContext — no user types cross the JS interop boundary.
BaseRendererControl.GetWCEnumTransform (helper extracted from BuildSequenceInfo) IL2070 ILLink preserves all fields of kept enum types; enum parameter property types are kept with their declaring component. Validated in the trimmed browser smoke (enum values render as camelCase strings, not numbers).
Utils.TryGetWCEnumName IL2070 Same enum-field preservation. Deliberately suppressed instead of annotated: DAM-annotated method parameters on component base classes trigger IL2111 in every consuming app, because OpenComponent<T> roots component members "via reflection".
IgniteUIBlazor ctor (module Register loop) IL2075 Library module types carry [IgbModule<TSelf>], preserving Register whenever the type is kept, so the lookup succeeds however the Type flowed here; third-party module types must be preserved by the app — documented in docs/TRIMMING.md.
IgniteUIBlazor.IsRuntimeValid IL2075 Probes optional RemoteJSRuntime.IsInitialized; in supported trim scenarios (WASM, MAUI BlazorWebView) the type doesn't exist and the probe correctly finds nothing. A string DynamicDependency can't be used (IL2035 when the Server assembly is absent).
RuntimeHelper ctor IL2075, IL2060, IL2026 net8-only InvokeUnmarshalled probe (API removed from the framework in net9+, binary-verified), preserved via the existing DynamicDependency; absence degrades to the raw-pointer InvokeVoid path that is the only path on net9+. IL2026: the DynamicDependency marks the runtime's RUC members (net10 GetValue/SetValue/…), which the probe filters out by name and never invokes.
IgbComponentRendererContainer.ComponentType IL2078 The backing field is only assigned through the annotated property; annotating the field itself would expose IL2110 to consuming apps.
JSDataSourceSchema.GetPropertiesFromType/GetFieldsFromType IL2067 Data-source boundary: item types are supplied by the app at runtime — documented requirement in docs/TRIMMING.md.
JSDataSourceSchema.CreateFromDictionary IL2075 Reflects only the Dictionary<string, object> indexer (both call sites guard on that type), which the library also uses statically — always preserved alongside this code.
UnmarshalledDataSource.ExtractSchema / ExtractSchemaFromType IL2072 / IL2067 Same boundary.

Guards & docs

  • Trim regression guard: dotnet_analyzer_diagnostic.category-Trimming.severity = error (plus category-SingleFile) in the repo .editorconfig — category bulk-config covers current and future IL2xxx codes, inert where the trim analyzer is off. Verified: removing a suppression fails the build with error IL2070. Suppression policy: docs/TRIMMING.md contributor section.
  • New docs/TRIMMING.md (linked from README): consumer guidance — preserving data item types (including nested complex types), module preloading, AOT status.
  • New tests/IgniteUI.Blazor.Lite.PublishSmoke: Blazor WASM app publishing the library trimmed (ILLinkTreatWarningsAsErrors, single-warn off, own trim analyzer on) with a browser checklist in its README; in the solution and published by CI after the library build. Named publish-scoped so the future AOT pass reuses it.
  • ci.yml gains the npm run copythemes step the release workflow already had — CI builds had no component themes in src/wwwroot (gitignored, npm-produced), which TrimmedPublishSmokeTest's clean-load fact caught as a theme-CSS 404 on its first CI run.
  • New TrimmedPublishSmokeTest (IntegrationTests, Category=TrimmedPublish): the browser checklist as Playwright facts over the trimmed net10.0 publish output — module preload survival, camelCase enum tokens, reflected data source, igcChange payload round-trip, clean load (no console errors/failed requests). Served by a minimal static-file host on a dynamic port (Infrastructure/TrimmedPublishServer.cs) that publishes the smoke app on demand; CI runs it via the existing unfiltered integration-test step, hitting the already-published fast path. Silent trims now fail CI instead of waiting for a manual check.

Verification

  • dotnet build (all 3 TFMs, rebuild): 0 IL diagnostics with the .editorconfig error gate active.
  • dotnet test: 959 passed / 0 failed on each of net8.0, net9.0, net10.0.
  • dotnet publish of PublishSmoke: 0 ILLink warnings (linker analysis warnings stay suppressed per the Blazor default — the framework's own assemblies emit them).
  • Headless-browser smoke against the trimmed publish output: enum attributes render as web-component tokens — camelCase by convention (variant="outlined", shape="circle" — enum fields survive trimming) and attribute-mapped (selection="single-required"[WCEnumName] field attributes survive too), the combo binds a 3-item reflected POCO list preserved per the docs/TRIMMING.md pattern, and a dispatched igcChange round-trips through the new date-range copy path into rendered output. These checks now run automatically as TrimmedPublishSmokeTest; the full integration suite (77 tests including the 5 new facts) passes.
  • Module registration verified with isolated trimmed publishes preloading a module whose component the app never references (IgbChatModule), through the Type-based path with no other rooting: without [IgbModule<TSelf>] the preload silently loses Register; with it, preserved. Plain type-level [DynamicallyAccessedMembers] (on the interface or the module class) was also tested and does not work: class-level DAM only activates for instantiated types (that's why it works on app data-item classes and on BaseRendererControl) or annotated GetType() flows — module classes are never instantiated, only typeof-referenced, hence the generic-attribute form whose DAM rides the attribute's type argument instead. The smoke app exercises the attribute-protected Type path permanently.

Behavioral notes

  • GatherSimpleAttributes previously deserialized with no options (default MaxDepth 64); it now honors Settings.JsonSerializerOptions.MaxDepth (library default 32) like its sibling call sites.
  • The AddIgniteUIBlazor overloads are unchanged — no source or binary breaking changes to module registration; IIgbModule and [IgbModule<TSelf>] are purely additive.
  • Object-initializing IgbDateRangeValue in the Change handler triggers two BL0005 analyzer warnings (parameter set outside component) — same class of pre-existing warnings as Chat.cs/Tabs.cs.
  • ⚠️ Known size limitation (not a trim-safety issue): MarshalByValueFactory.CreateInstance's static switch constructs every marshal-by-value type, so all event-args types survive trimming and pull in thin shells of their component types (e.g. IgbTab keeps Type + 4 property accessors in an app that never uses tabs). Bounded — unused components don't survive in full — and reclaiming it needs pay-for-play event-args registration, deferred to the interop rework.

🤖 Generated with Claude Code

Comment on lines +452 to +470
foreach (var f in enumType.GetFields())
{
if (f.IsPublic && !f.IsSpecialName)
{
foreach (var attr in f.GetCustomAttributes(true))
{
if (attr.GetType().Name == "WCEnumNameAttribute")
{
if (wcEnumTransform == null)
{
wcEnumTransform = new Dictionary<string, string>();
}
var wc = (WCEnumNameAttribute)attr;
var wcEnumName = Camelize(wc.Name);
wcEnumTransform.Add(f.Name.ToLower(), wcEnumName);
}
}
}
}
Comment on lines +456 to +468
foreach (var attr in f.GetCustomAttributes(true))
{
if (attr.GetType().Name == "WCEnumNameAttribute")
{
if (wcEnumTransform == null)
{
wcEnumTransform = new Dictionary<string, string>();
}
var wc = (WCEnumNameAttribute)attr;
var wcEnumName = Camelize(wc.Name);
wcEnumTransform.Add(f.Name.ToLower(), wcEnumName);
}
}
Comment thread tests/IgniteUI.Blazor.Tests/ServiceRegistrationTests.cs Dismissed
Comment thread tests/IgniteUI.Blazor.Lite.IntegrationTests/Infrastructure/TrimmedPublishServer.cs Dismissed
Comment thread tests/IgniteUI.Blazor.Lite.IntegrationTests/Infrastructure/TrimmedPublishServer.cs Dismissed
Comment thread tests/IgniteUI.Blazor.Lite.IntegrationTests/Infrastructure/TrimmedPublishServer.cs Dismissed
@damyanpetev damyanpetev added the squash-merge Merge PR with "Squash and Merge" option label Aug 27, 2026
@damyanpetev
damyanpetev requested a lite review from Copilot August 27, 2026 09:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes IgniteUI.Blazor.Lite safe to consume from trimmed Blazor WebAssembly publishes by eliminating (or narrowly suppressing with justification) ILLink/trim-analyzer warnings. It introduces trim-safe JSON interop via System.Text.Json source generation, adds a trim-safe mechanism for Type-based module preloading, and adds docs + automated publish-smoke browser checks to prevent regressions.

Changes:

  • Switch JSON interop to source-generated JsonTypeInfo via IgbJsonContext, updating BaseRendererControl to use typed JsonSerializer overloads.
  • Introduce trim-safe module preloading via new IIgbModule + self-referencing [IgbModule<TSelf>], and apply it across *Module types.
  • Add trimming docs and regression guards: .editorconfig analyzer gates, publish-smoke app, and Playwright-based trimmed publish integration test.

Reviewed changes

Copilot reviewed 104 out of 104 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/IgniteUI.Blazor.Tests/ServiceRegistrationTests.cs Adds drift-guard test ensuring every module has a self-referencing [IgbModule<TSelf>].
tests/IgniteUI.Blazor.Lite.PublishSmoke/wwwroot/index.html Adds minimal WASM smoke app host page referencing Ignite UI static assets.
tests/IgniteUI.Blazor.Lite.PublishSmoke/README.md Documents why/when/how to verify trimming via publish + browser checklist.
tests/IgniteUI.Blazor.Lite.PublishSmoke/Properties/launchSettings.json Adds dev launch profile for the publish-smoke app.
tests/IgniteUI.Blazor.Lite.PublishSmoke/Program.cs Registers Ignite UI + modules and exercises Type-based module preloading under trimming.
tests/IgniteUI.Blazor.Lite.PublishSmoke/IgniteUI.Blazor.Lite.PublishSmoke.csproj Adds multi-TFM WASM app configured to fail publish on any ILLink warnings.
tests/IgniteUI.Blazor.Lite.PublishSmoke/App.razor Implements in-app UI checks for enums, data-source reflection, module preload, and event payloads.
tests/IgniteUI.Blazor.Lite.PublishSmoke/_Imports.razor Adds imports required by the smoke app (incl. trimming annotations).
tests/IgniteUI.Blazor.Lite.IntegrationTests/TrimmedPublishSmokeTest.cs Adds Playwright automated browser checks over trimmed publish output.
tests/IgniteUI.Blazor.Lite.IntegrationTests/Infrastructure/TrimmedPublishServer.cs Adds server to publish-on-demand and serve trimmed output as static files for browser tests.
src/IgniteUI.Blazor.Lite.csproj Enables IsTrimmable=true for the library build.
src/componentsBase/Utils.cs Adds trim suppression for enum-field reflection used by WC enum-name mapping.
src/componentsBase/UnmarshalledDataSource.cs Adds trimming suppressions/annotations for app-provided data item type reflection boundary.
src/componentsBase/RuntimeHelper.cs Adds trimming suppressions around framework runtime probing for net8-only paths.
src/componentsBase/JsonDataSourceSchema.cs Adds trimming suppressions around reflection over app data item types and dictionary indexer.
src/componentsBase/IgbModule.cs Adds IIgbModule and the [IgbModule<TSelf>] attribute retention mechanism.
src/componentsBase/IgbJsonContext.cs Adds source-generated JSON context for the closed set of interop “wire shapes”.
src/componentsBase/IgbComponentRendererContainer.cs Annotates ComponentType with DAM and suppresses IL2078 on the property flow.
src/componentsBase/DynamicContentHolder.cs Annotates dynamic Type flows used with RenderTreeBuilder.OpenComponent(Type).
src/componentsBase/BaseRendererControl.cs Reworks JSON serialize/deserialize to use JsonTypeInfo and adds focused trim suppressions/helpers.
src/components/Blazor/TreeModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/TreeItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/TooltipModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ToggleButtonModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/ToastModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/TileModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/TileManagerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ThemeProviderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/TextareaModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/TabsModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/TabModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SwitchModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/StepperModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/StepModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SplitterModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/SnackbarModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/SliderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/SliderLabelModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SliderBaseModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SelectModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/SelectItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SelectHeaderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/SelectGroupModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/RippleModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/RatingSymbolModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/RatingModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/RangeSliderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/RadioModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/RadioGroupModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/NavDrawerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/NavDrawerItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/NavDrawerHeaderItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/NavbarModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/MaskInputModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ListModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ListItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/ListHeaderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/LinearProgressModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/InputModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/IconModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/IconButtonModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/HighlightModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ExpansionPanelModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DropdownModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DropdownItemModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/DropdownHeaderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/DropdownGroupModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/DividerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DialogModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DateTimeInputModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DateRangePickerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/DateRangePicker.cs Replaces JSON round-trip in Change handler with direct Start/End copy for trim/perf.
src/components/Blazor/DatePickerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ComboModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CircularProgressModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CircularGradientModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ChipModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CheckboxModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CheckboxBaseModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/ChatModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CarouselSlideModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CarouselModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CarouselIndicatorModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CardModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CardMediaModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CardHeaderModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CardContentModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CardActionsModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/CalendarModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/CalendarBaseModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule (obsolete no-op module).
src/components/Blazor/ButtonModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/ButtonGroupModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/BannerModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/BadgeModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/AvatarModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
src/components/Blazor/AccordionModule.cs Applies [IgbModule<TSelf>] and implements IIgbModule.
README.md Adds consumer-facing note + link to trimming guidance.
IgniteUI.Blazor.Lite.slnx Adds PublishSmoke project to the solution.
docs/TRIMMING.md Adds trimming guidance for consumers and contributor policy.
Directory.Packages.props Adds per-TFM WebAssembly package versions for the smoke app.
.github/workflows/ci.yml Adds theme copy step and publishes smoke app per TFM in CI.
.github/CONTRIBUTING.md Updates contributor guidance to mention trimming analyzer gate and policy doc.
.editorconfig Enforces trimming/single-file analyzer categories as errors repo-wide.
.agents/skills/igniteui-blazor-lite-trimming/SKILL.md Adds an agent skill describing trimming rules and verification steps.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +70 to +73
using var process = Process.Start(publish)!;
var stderr = process.StandardError.ReadToEndAsync();
var output = process.StandardOutput.ReadToEnd() + stderr.GetAwaiter().GetResult();
process.WaitForExit();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature refactoring squash-merge Merge PR with "Squash and Merge" option 🧪 ci: tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enable trim analysis

2 participants