feat(lib): Enable Nullable analysis and fix warnings - #365
Conversation
… return types in UnmarshalledDataSource
There was a problem hiding this comment.
Pull request overview
Enables C# nullable reference type analysis across the Ignite UI for Blazor codebase (including the Lite project) and updates library code, stories, and tests to address the resulting warnings—primarily by adding nullable annotations, null guards, and safer event JSON decoding.
Changes:
- Enabled
<Nullable>enable</Nullable>forIgniteUI.Blazor.Liteand applied nullable annotations across the library. - Updated event args / JSON (de)serialization paths to tolerate
nulldictionaries and nullable payload members. - Updated unit tests and stories to compile under nullable analysis (mostly via
!null-forgiving in assertions/handlers).
Reviewed changes
Copilot reviewed 158 out of 181 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/IgniteUI.Blazor.Tests/TreeTests.cs | Update test asserts for nullable event args/results |
| tests/IgniteUI.Blazor.Tests/TileManagerTests.cs | Update test asserts for nullable event args/results |
| tests/IgniteUI.Blazor.Tests/TabsTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/SwitchTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/StepperTests.cs | Update test asserts for nullable event args/results |
| tests/IgniteUI.Blazor.Tests/SplitterTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/SelectTests.cs | Update test asserts for nullable event args/results |
| tests/IgniteUI.Blazor.Tests/RangeSliderTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/RadioTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/DropdownTests.cs | Update test asserts for nullable results |
| tests/IgniteUI.Blazor.Tests/DateRangePickerTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/ComboTests.cs | Update test asserts for nullable event args/results |
| tests/IgniteUI.Blazor.Tests/CheckboxTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/ChatTests.cs | Update test asserts for nullable event args |
| tests/IgniteUI.Blazor.Tests/CalendarTests.cs | Update test asserts/casts for nullable event payload |
| tests/IgniteUI.Blazor.Lite.TestBed/Components/Common/TestUtil.cs | Nullability adjustments for date range comparison |
| stories/Components/Stories/Chat.stories.razor | Update story event handlers for nullable message payloads |
| src/IgniteUI.Blazor.Lite.csproj | Enable nullable analysis for Lite project |
| src/componentsBase/WebViewCallback.cs | Nullability adjustments in JS-invokable callbacks/batch handling |
| src/componentsBase/WebInputs/TreeItem.cs | CascadingParameter made nullable |
| src/componentsBase/WebInputs/Tree.cs | Nullable backing field for content items |
| src/componentsBase/WebInputs/TileManager.cs | Nullable backing field for content items |
| src/componentsBase/WebInputs/Tile.cs | CascadingParameter made nullable |
| src/componentsBase/WebInputs/SelectItem.cs | CascadingParameter made nullable |
| src/componentsBase/WebInputs/Select.cs | Nullable backing field for content items |
| src/componentsBase/WebInputs/Rating.cs | Injected logger nullability + parameter coercion nullability |
| src/componentsBase/WebInputs/Input.cs | Injected logger nullability + parameter coercion nullability |
| src/componentsBase/WebInputs/DropdownItem.cs | CascadingParameter made nullable |
| src/componentsBase/WebInputs/Dropdown.cs | Nullable args arrays + nullable backing field for content items |
| src/componentsBase/WebInputs/DateTimeInput.cs | Nullable args arrays passed into interop invocations |
| src/componentsBase/WebInputs/Chat.cs | Nullable args arrays passed into interop invocations |
| src/componentsBase/WebInputs/Accordion.cs | Nullable backing fields + nullable CascadingParameter |
| src/componentsBase/Utils.cs | Update signature for nullable enum member name/out name |
| src/componentsBase/RuntimeHelper.cs | Make runtime/delegates nullable and adjust unmarshalled call plumbing |
| src/componentsBase/RendererMessage.cs | Make payload dictionary values nullable |
| src/componentsBase/RefSink.cs | Ref sink interface updated for nullable ref values/items |
| src/componentsBase/MarshalByValueFactory.cs | Allow nullable typeName / nullable CreateInstance result |
| src/componentsBase/JsonSerializable.cs | Nullability updates for serialization delegate/context/interface |
| src/componentsBase/IgbTemplateContent.razor | Template/context parameters updated for nullable analysis |
| src/componentsBase/IgbComponentRendererContainer.cs | Make component type/root component nullable + nullable event |
| src/componentsBase/EventCallbackExtensions.cs | Reflection field handles made nullable + guarded access |
| src/componentsBase/DataAdapters.cs | Make adapter backing fields/properties nullable for analysis |
| src/componentsBase/CollectionAdapter.cs | Make internal fields nullable + add null-forgiving where needed |
| src/components/Blazor/VoidEventArgs.cs | Nullable event JSON args dictionary types |
| src/components/Blazor/TreeSelectionEventArgsDetail.cs | Nullable selection array + nullable event args dictionaries |
| src/components/Blazor/TreeSelectionEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/TreeItemComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/TreeItem.cs | Nullable parameters/returns + nullable args arrays for interop calls |
| src/components/Blazor/ToggleButton.cs | Nullable parameters + nullable args arrays for interop calls |
| src/components/Blazor/TileComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/TileChangeStateEventArgsDetail.cs | Nullable tile + nullable event args dictionaries |
| src/components/Blazor/TileChangeStateEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ThemeProvider.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Tabs.cs | Nullable backing fields/return + nullable args arrays for interop calls |
| src/components/Blazor/TabComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/Tab.cs | Nullable cascading parent + nullable label + nullable args arrays |
| src/components/Blazor/Step.cs | Nullable args arrays for interop calls |
| src/components/Blazor/SplitterResizeEventArgsDetail.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/SplitterResizeEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/Splitter.cs | Nullable args arrays + nullable script refs + nullable callback arg types |
| src/components/Blazor/Snackbar.cs | Nullable parameters + nullable script refs + nullable callback arg types |
| src/components/Blazor/SliderLabel.cs | Nullable args arrays for interop calls |
| src/components/Blazor/SliderBase.cs | Nullable parameters/options + nullable args arrays + null-forgiving cast |
| src/components/Blazor/SelectItemComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/SelectHeader.cs | Nullable args arrays for interop calls |
| src/components/Blazor/SelectGroup.cs | Nullable items array + nullable args arrays for interop calls |
| src/components/Blazor/Ripple.cs | Nullable args arrays for interop calls |
| src/components/Blazor/RatingSymbol.cs | Nullable args arrays for interop calls |
| src/components/Blazor/RangeSliderValueEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/RangeSliderValue.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/RangeSlider.cs | Nullable aria labels + nullable script refs + nullable callback arg types |
| src/components/Blazor/RadioGroup.cs | Nullable value/returns + nullable args arrays + nullable script refs |
| src/components/Blazor/RadioChangeEventArgsDetail.cs | Nullable value + nullable event args dictionaries |
| src/components/Blazor/RadioChangeEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ProgressBase.cs | Nullable label format + nullable args arrays |
| src/components/Blazor/NumberEventArgs.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/NavDrawerItem.cs | Nullable args arrays for interop calls |
| src/components/Blazor/NavDrawerHeaderItem.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Navbar.cs | Nullable args arrays for interop calls |
| src/components/Blazor/MaskInput.cs | Nullable parameters/returns + nullable args arrays + nullable script refs |
| src/components/Blazor/ListItem.cs | Nullable args arrays for interop calls |
| src/components/Blazor/ListHeader.cs | Nullable args arrays for interop calls |
| src/components/Blazor/List.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Input.cs | Nullable parameters/returns + nullable args arrays + nullable script refs |
| src/components/Blazor/IconMeta.cs | Nullable collection + nullable event args dictionaries + fallback name |
| src/components/Blazor/IconButton.cs | Nullable parameters + doc/comment + nullable args arrays for interop calls |
| src/components/Blazor/Icon.cs | Nullable parameters + nullable args arrays for interop calls |
| src/components/Blazor/HighlightNavigation.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/Highlight.cs | Nullable SearchText + nullable args arrays for interop calls |
| src/components/Blazor/FormatSpecifier.cs | Nullable return values + nullable event args dictionaries |
| src/components/Blazor/FilteringOptions.cs | Nullable filter key |
| src/components/Blazor/ExpansionPanelComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/DropdownItemComponentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/DropdownHeader.cs | Nullable args arrays for interop calls |
| src/components/Blazor/DropdownGroup.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Divider.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Dialog.cs | Nullable parameters/refs + nullable args arrays for interop calls |
| src/components/Blazor/DateRangeValueEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/DateRangeValueDetail.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/DateRangeDescriptor.cs | Nullable date range value |
| src/components/Blazor/CustomDateRange.cs | Nullable label/date range |
| src/components/Blazor/ComponentValueChangedEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ComponentDateValueChangedEventArgs.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/ComponentDataValueChangedEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ComponentBoolValueChangedEventArgs.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/ComboChangeEventArgsDetail.cs | Nullable arrays/refs/scripts + nullable event args dictionaries |
| src/components/Blazor/ComboChangeEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/CircularGradient.cs | Nullable parameters + nullable args arrays |
| src/components/Blazor/Chip.cs | Nullable args arrays + nullable script refs |
| src/components/Blazor/CheckboxChangeEventArgsDetail.cs | Nullable value + nullable event args dictionaries |
| src/components/Blazor/CheckboxChangeEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ChatRenderContext.cs | Nullable instance |
| src/components/Blazor/ChatOptions.cs | Nullable strings/arrays/renderers |
| src/components/Blazor/ChatMessageRenderContext.cs | Nullable message |
| src/components/Blazor/ChatMessageReactionEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ChatMessageReaction.cs | Nullable message/reaction + nullable event args dictionaries |
| src/components/Blazor/ChatMessageEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ChatMessageAttachmentEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ChatMessageAttachment.cs | Nullable fields + nullable event args dictionaries + fallback name |
| src/components/Blazor/ChatMessage.cs | Nullable fields/arrays + nullable event args dictionaries |
| src/components/Blazor/ChatInputRenderContext.cs | Nullable value |
| src/components/Blazor/ChatDraftMessage.cs | Nullable fields/attachments + nullable event args dictionaries |
| src/components/Blazor/ChatAttachmentRenderContext.cs | Nullable attachment |
| src/components/Blazor/CarouselSlide.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CarouselIndicator.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CardMedia.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CardHeader.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CardContent.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CardActions.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Card.cs | Nullable args arrays for interop calls |
| src/components/Blazor/CalendarResourceStrings.cs | Nullable resource string parameters |
| src/components/Blazor/CalendarFormatOptions.cs | Nullable weekday/month + nullable event args dictionaries |
| src/components/Blazor/CalendarBase.cs | Nullable locale/resource strings + nullable args arrays |
| src/components/Blazor/ButtonGroup.cs | Nullable selected items + nullable args arrays + nullable script refs |
| src/components/Blazor/BaseOptionLike.cs | Nullable value + nullable args arrays |
| src/components/Blazor/BaseComboBox.cs | Nullable args arrays for interop calls |
| src/components/Blazor/BaseAlertLike.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Banner.cs | Nullable args arrays + nullable script refs |
| src/components/Blazor/Badge.cs | Nullable args arrays for interop calls |
| src/components/Blazor/Avatar.cs | Nullable parameters + nullable args arrays |
| src/components/Blazor/ActiveStepChangingEventArgsDetail.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/ActiveStepChangingEventArgs.cs | Nullable detail + nullable event args dictionaries |
| src/components/Blazor/ActiveStepChangedEventArgsDetail.cs | Nullable event args dictionaries + null checks |
| src/components/Blazor/ActiveStepChangedEventArgs.cs | Nullable detail + nullable event args dictionaries |
Suppressed comments (1)
src/componentsBase/DataAdapters.cs:46
RemoteJson.Uriis annotated as nullable, but it is always initialized via the constructor. Keeping it nullable makesToRef()potentially produce malformed refs ("json:::") and pushes unnecessary nullability into callers.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: MayaKirova <10397980+MayaKirova@users.noreply.github.com>
…thread Fix Copilot review findings: null-safety, dash encoding, delegate mismatch
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ui-blazor into mkirova/nullable
| } | ||
|
|
||
| //Console.WriteLine("notifying insert item"); | ||
| if (refItem == null) |
There was a problem hiding this comment.
I can't think of a proper case of whether we should we support adding/removing null, but with this if a user tries adding null refName it won't work.
Anyway I think it can stay as is.
There was a problem hiding this comment.
I don't think it makes sense to have null objects in the data source.
I can make refItem non-nullable so that users cannot explicitly pass null without getting a warning/error if that makes more sense.
There was a problem hiding this comment.
Although, now that I look at the sample, this is not part of the public API. The logic that syncs them is internal, so not sure if we can prevent the user from adding nulls in his own collection.
There was a problem hiding this comment.
Currently even just binding to collection that has a null, doesn't work, for example:
private static ObservableCollection<Product?> CreateProducts() =>
[
new(1, "Chai"),
null,
new(2, "Chang"),
new(3, "Aniseed Syrup"),
];
And if we decide to support nulls all scenarios should work, including things like updating a null value to something else.
For the time being, I don't think we should add support for this.
I guess we should just decide if it's better for nulls to be discarded (like it does now) or if it should throw an error.
There was a problem hiding this comment.
While null elements in collections are technically possible, it's probably exceeding rare if at all (not like there are null records in a DB tables, a join perhaps could), so while this might be worth looking into and making the behavior explicit and consistent - way out of scope for this PR's goal.
Anyway, the specific change has been reverted and the pre-existing flow restore more/less as it was.
| return new IgbActiveStepChangedEventArgs(); | ||
| return new IgbActiveStepChangedEventArgs | ||
| { | ||
| Detail = new IgbActiveStepChangedEventArgsDetail() |
There was a problem hiding this comment.
Just a small note, I think this is a bit extra for now, unless we plan to do it for all event args.
The full product made IgbDatePicker and IgbDateTimeInput Value, Min and Max nullable in 25.1.63, the shipped item templates bind a DateTime? field, and null is the only way to clear the element from Blazor. Generic value binding and EditForm integration for the date components are a separate change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ReturnToString never returns null, so the getters built on it return string. IgcChatMessage id, text and sender, IgcChatMessageAttachment id and IgcTileChangeStateEventArgs tile are required on the client. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… operators ConvertReturnValue returns object?, so the ReturnTo* guards and the component-side null checks are live again instead of being hidden behind null!. Dictionary getters return the raw value, the method-wide CS8604 pragmas are replaced by per-site checks, BuildSequenceInfo runs lazily rather than from the constructor, and collection notifications pass null items through as before. IgBlazor keeps the throwing getter: a nullable property would need about 150 guards at the module registration sites. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…htened Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Description
Enable nullable analysis repository-wide and fix all warnings that emerged from it.
This change also preserves nullable items in observable data sources. Null insertions, removals, and replacements now propagate through both the JSON and unmarshalled data channels.
The nullable cleanup includes 16 binary-breaking public signature changes documented in
CHANGELOG.md. This PR therefore requires a major-version release.Type of Change (check all that apply):
Component(s) / Area(s) Affected:
All components and shared data-source infrastructure.
How Has This Been Tested?
Unit coverage includes nullable collection insert, remove, and replacement transitions before and after schema inference on both data transport channels.
Checklist:
README.MDCHANGELOG.MDupdates for newly added functionalityCloses #347