Skip to content

dev: enable nullable where no errors, treat warnings as errors#3750

Open
marksvc wants to merge 1 commit intomasterfrom
task/more-nullable
Open

dev: enable nullable where no errors, treat warnings as errors#3750
marksvc wants to merge 1 commit intomasterfrom
task/more-nullable

Conversation

@marksvc
Copy link
Collaborator

@marksvc marksvc commented Mar 18, 2026

Files with #nullable enable will have an error from new code like
string foo = null. (Instead of string? foo = null.)


Open with Devin

This change is Reviewable

@marksvc marksvc marked this pull request as draft March 18, 2026 23:02
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@marksvc marksvc added testing not required e2e Run e2e tests for this pull request labels Mar 18, 2026
@marksvc
Copy link
Collaborator Author

marksvc commented Mar 18, 2026

This takes a step toward our C# code enforcing non-nullable type usage.

@marksvc marksvc marked this pull request as ready for review March 18, 2026 23:11
Copy link
Collaborator

@RaymondLuong3 RaymondLuong3 left a comment

Choose a reason for hiding this comment

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

Why not just enable nullable from the .csproj files?
<nullable>enable</nullable>

@RaymondLuong3 reviewed all commit messages and made 1 comment.
Reviewable status: 0 of 255 files reviewed, all discussions resolved.

@RaymondLuong3 RaymondLuong3 self-assigned this Mar 19, 2026
@marksvc
Copy link
Collaborator Author

marksvc commented Mar 19, 2026

If we enable nullable from the csproj files now, it would apply that setting to all C# files in the project. We would get many errors where things like string foo = null are done.
This PR just sets 'nullable enable' on files that won't produce such errors. For files that do not have #nullable enable, when we work on those, we can one at a time change string foo = null to string? foo = null, and set #nullable enable on that file.
Once all files can have 'nullable enable' without errors, then we can set <Nullable>enable</Nullable> project wide in the csproj files and remove the #nullable per-file settings.

@Nateowami
Copy link
Collaborator

@marksvc Is it possible to enable it globally, and then selectively, at a file level, disable it, so all new code will automatically have it enabled?

@marksvc marksvc force-pushed the task/more-nullable branch from e3aeb71 to 1eef167 Compare March 20, 2026 19:29
Copy link
Collaborator Author

@marksvc marksvc left a comment

Choose a reason for hiding this comment

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

@Nateowami Thank you for suggesting that. There are around 250 files that can have nullable enabled, and about 161 files that can not (without further work). Now the csproj files enable nullable, which will desirably apply to new files automatically, and not-yet-migrated/fixed-up files are marked with #nullable disable warnings.

When we change a file so it conforms with non-nullable types, we can remove its #nullable disable warnings line.

In file src/SIL.XForge.Scripture/Pages/Shared/_SelectLanguagePartial.cshtml I was not successful applying #nullable disable warnings. Instead, I modify the code so it does not show the <select> element if requestCulture != null. My understanding is that the asp-for is both an input and output binding. It would be read from to show the current language in the element, and written to when a language is selected. Neither of those are going to work if requestCulture is null, and AI suggests the page would show an error in that case. With the change, it will not try to read to or write from requestCulture if it is null, and will just omit the language chooser from the page in that case.

@marksvc made 1 comment.
Reviewable status: 0 of 255 files reviewed, all discussions resolved (waiting on RaymondLuong3).

Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +11 to 14
#nullable disable warnings
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
InterfaceLanguage? locale = LocOptions.Value.SupportedUICultures?.Where(c =>
SharedResource.Cultures[c.IetfLanguageTag].Tags.Contains(requestCulture.RequestCulture.UICulture.Name)

Choose a reason for hiding this comment

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

🚩 Inconsistent null handling between _Footer.cshtml and _SelectLanguagePartial.cshtml

Both _Footer.cshtml:12 and _SelectLanguagePartial.cshtml:11 obtain requestCulture from Context.Features.Get<IRequestCultureFeature>(), which can return null. The PR properly adds a null check in _SelectLanguagePartial.cshtml:31 (@if (requestCulture != null)), but in _Footer.cshtml:11 it only adds #nullable disable warnings to suppress the compiler warning. If requestCulture is null, _Footer.cshtml:14 would throw a NullReferenceException when accessing requestCulture.RequestCulture.UICulture.Name. While IRequestCultureFeature should always be present when UseRequestLocalization middleware is configured (src/SIL.XForge.Scripture/Startup.cs:252), this is a pre-existing inconsistency that the PR's nullable migration makes more visible. The AGENTS.md rule 'Corner-cases happen. They should be handled in code' suggests the _Footer.cshtml should also get a proper null check rather than just warning suppression.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixing potential NREs is for possible followup, and not intended to be part of this PR. It was done in _SelectLanguagePartial.cshtml where I did not seem to be able to just #nullable disable warnings.

@codecov
Copy link

codecov bot commented Mar 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.31%. Comparing base (e8ae5b7) to head (1eef167).
⚠️ Report is 3 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3750   +/-   ##
=======================================
  Coverage   81.31%   81.31%           
=======================================
  Files         620      620           
  Lines       39079    39079           
  Branches     6376     6376           
=======================================
  Hits        31778    31778           
  Misses       6329     6329           
  Partials      972      972           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@Nateowami Nateowami left a comment

Choose a reason for hiding this comment

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

Changes look good, except that I can't build locally due to warnings being treated as errors, and these two errors being present:

src/SIL.XForge.Scripture/Controllers/OnboardingRequestRpcController.cs(490,41): error CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [/home/nate/src/web-xforge/src/SIL.XForge.Scripture/SIL.XForge.Scripture.csproj]
src/SIL.XForge.Scripture/Controllers/OnboardingRequestRpcController.cs(544,41): error CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [/home/nate/src/web-xforge/src/SIL.XForge.Scripture/SIL.XForge.Scripture.csproj]

@Nateowami reviewed 418 files and all commit messages, made 1 comment, and resolved 1 discussion.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on marksvc).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

e2e Run e2e tests for this pull request testing not required

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants