Skip to content

CodeQL 13: chore: additional style fixes (ternary, complex-block, implicit-conversion)#199

Open
rlorenzo wants to merge 2 commits into
mainfrom
codeql/13-final-sweep
Open

CodeQL 13: chore: additional style fixes (ternary, complex-block, implicit-conversion)#199
rlorenzo wants to merge 2 commits into
mainfrom
codeql/13-final-sweep

Conversation

@rlorenzo
Copy link
Copy Markdown
Contributor

@rlorenzo rlorenzo commented May 13, 2026

Summary

Final sweep of CodeQL style alerts that earlier PRs left as wontfix:

  • js/implicit-operand-conversion (2): course-import-dialog.test.ts:72,96 - narrow the union check by combining typeof === 'object' with instanceof Error, then explicit as Error cast on the truthy branch.
  • cs/complex-block (1): MeritMultiYearService.CalculateMedian - five for-loops appending to a List collapsed into chained Enumerable.Repeat(...).Concat(...).
  • cs/missed-ternary-operator (5) that were deferred:
    • GradYearClassLevel.cs:63 - case-4 if-else assignment
    • RotationsController.cs:63 - serviceId.HasValue ? GetRotationsByServiceAsync : GetRotationsAsync
    • UinformService.cs:247 - response.IsSuccessStatusCode ? Deserialize : new ErrorResponse
    • EffortAuditService.cs:605 - termCode-keyed IQueryable selection
    • Also picks up the earlier useless-tostring fix on GradYearClassLevel.cs:57,60,69 (no-op vs PR CodeQL 12: chore: style sweep for remaining CodeQL alerts #198 which has the same change).

Context

Thirteenth in the CodeQL N: cleanup series.

Test plan

  • npm run test:backend - 1946 tests passing
  • Pre-commit lint+test+verify all passed

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors control flow across six files by converting if/else conditionals to ternary expressions, replacing manual loops with LINQ, removing redundant .ToString() calls, and tightening type checks in tests. All changes simplify code without altering behavior.

Changes

Code Simplification Refactoring

Layer / File(s) Summary
Test error type checking refinement
VueApp/src/Effort/__tests__/course-import-dialog.test.ts
Error exception handling tests now validate Error type with an explicit isError boolean combining typeof and instanceof checks instead of inline conditionals, strengthening type safety for non-Error exception cases.
Control flow simplification across services
web/Areas/ClinicalScheduler/Controllers/RotationsController.cs, web/Areas/Effort/Services/EffortAuditService.cs, web/Areas/Effort/Services/MeritMultiYearService.cs, web/Areas/RAPS/Services/UinformService.cs, web/Areas/Students/Services/GradYearClassLevel.cs
RotationsController refactors async method selection to ternary; EffortAuditService builds courseIds via conditional expression; MeritMultiYearService converts median response-list construction from loops to LINQ with Enumerable.Repeat and Concat; UinformService simplifies response handling to a single conditional return; GradYearClassLevel removes redundant .ToString() in string composition and replaces multi-branch logic with conditional expressions.

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • bsedwards
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses CodeQL style alerts unrelated to the linked issue #39 (System.Linq.Dynamic.Core v1.6.0 upgrade with CVE-2024-51417 fix). No code changes address the dependency upgrade, ParsingConfig default behavior changes, or CVE verification required by #39. Either link the correct CodeQL cleanup issue if one exists, or clarify whether this PR should address #39's security upgrade and behavioral verification requirements instead.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main changes: CodeQL style fixes addressing implicit-conversion, complex-block, and ternary-operator alerts across multiple files.
Description check ✅ Passed The description clearly explains the CodeQL alerts being fixed, lists specific file locations and refactoring approaches, and provides test results confirming no regressions.
Out of Scope Changes check ✅ Passed All six file changes implement announced CodeQL style fixes (ternary operators, complex-block simplification, implicit-conversion narrowing). No unrelated refactoring or feature changes are present.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codeql/13-final-sweep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

Bundle Report

Bundle size has no change ✅

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 13, 2026

Codecov Report

❌ Patch coverage is 13.63636% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.97%. Comparing base (5949e52) to head (e9d677a).

Files with missing lines Patch % Lines
web/Areas/Effort/Services/MeritMultiYearService.cs 0.00% 7 Missing ⚠️
web/Areas/Students/Services/GradYearClassLevel.cs 0.00% 5 Missing ⚠️
web/Areas/Effort/Services/EffortAuditService.cs 0.00% 4 Missing ⚠️
web/Areas/RAPS/Services/UinformService.cs 0.00% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #199   +/-   ##
=======================================
  Coverage   42.96%   42.97%           
=======================================
  Files         877      877           
  Lines       51468    51450   -18     
  Branches     4802     4797    -5     
=======================================
- Hits        22113    22109    -4     
+ Misses      28831    28817   -14     
  Partials      524      524           
Flag Coverage Δ
backend 43.05% <13.63%> (+<0.01%) ⬆️
frontend 41.34% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

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

@rlorenzo
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/Areas/Effort/Services/MeritMultiYearService.cs`:
- Around line 868-875: The code builds the responses list using
Enumerable.Repeat with n1..n5 but doesn't validate those counts; negative counts
will throw ArgumentOutOfRangeException. Before calling Enumerable.Repeat (the
block that constructs responses), clamp or sanitize the n1, n2, n3, n4, n5
values to a non-negative integer (e.g., Math.Max(0, nX) or a small helper
NormalizeCount) and then use those sanitized variables when creating responses
so Enumerable.Repeat(...) never receives a negative count.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 079a90be-124e-4667-b457-197ab51abdda

📥 Commits

Reviewing files that changed from the base of the PR and between 38de1ad and 8fc03de.

📒 Files selected for processing (6)
  • VueApp/src/Effort/__tests__/course-import-dialog.test.ts
  • web/Areas/ClinicalScheduler/Controllers/RotationsController.cs
  • web/Areas/Effort/Services/EffortAuditService.cs
  • web/Areas/Effort/Services/MeritMultiYearService.cs
  • web/Areas/RAPS/Services/UinformService.cs
  • web/Areas/Students/Services/GradYearClassLevel.cs

Comment on lines +868 to +875
if (n1 + n2 + n3 + n4 + n5 == 0) return null;

var responses = Enumerable.Repeat(1m, n1)
.Concat(Enumerable.Repeat(2m, n2))
.Concat(Enumerable.Repeat(3m, n3))
.Concat(Enumerable.Repeat(4m, n4))
.Concat(Enumerable.Repeat(5m, n5))
.ToList();
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In .NET, does Enumerable.Repeat<T>(element, count) throw an exception when count is negative? Please cite the official Microsoft docs.

💡 Result:

Yes, in.NET, the Enumerable.Repeat(TResult, Int32) method throws an ArgumentOutOfRangeException if the count parameter is less than 0 [1][2][3]. According to the official Microsoft documentation, the count argument represents the number of times to repeat the value in the generated sequence, and it must be a non-negative integer [1][2][3]. If a negative value is provided, the method explicitly throws an ArgumentOutOfRangeException [1][2][3].

Citations:


🏁 Script executed:

cd web/Areas/Effort/Services && wc -l MeritMultiYearService.cs

Repository: ucdavis/VIPER

Length of output: 87


🏁 Script executed:

cd web/Areas/Effort/Services && sed -n '850,900p' MeritMultiYearService.cs

Repository: ucdavis/VIPER

Length of output: 1732


🏁 Script executed:

cd web/Areas/Effort/Services && sed -n '1,50p' MeritMultiYearService.cs | head -50

Repository: ucdavis/VIPER

Length of output: 1734


🏁 Script executed:

cd web/Areas/Effort/Services && rg 'CalculateMedian' -n

Repository: ucdavis/VIPER

Length of output: 648


🏁 Script executed:

cd web/Areas/Effort/Services && sed -n '1,900p' MeritMultiYearService.cs | rg -B 10 'CalculateMedian\(' | head -100

Repository: ucdavis/VIPER

Length of output: 923


🏁 Script executed:

cd web/Areas/Effort/Services && sed -n '420,460p' MeritMultiYearService.cs

Repository: ucdavis/VIPER

Length of output: 1648


🏁 Script executed:

cd web/Areas/Effort/Services && sed -n '300,450p' MeritMultiYearService.cs | grep -n -B 30 'CalculateMedian'

Repository: ucdavis/VIPER

Length of output: 1296


🏁 Script executed:

cd web && find . -name '*.cs' -type f | xargs rg 'class EvalsMultiyearRow|record EvalsMultiyearRow|struct EvalsMultiyearRow' -A 20

Repository: ucdavis/VIPER

Length of output: 2139


🏁 Script executed:

cd web && rg 'EvalsMultiyearRow' --type cs | grep -i 'select\|new EvalsMultiyearRow'

Repository: ucdavis/VIPER

Length of output: 150


🏁 Script executed:

cd web && sed -n '1,1000p' Areas/Effort/Services/MeritMultiYearService.cs | grep -n -A 30 'new EvalsMultiyearRow'

Repository: ucdavis/VIPER

Length of output: 2066


Guard against negative bucket counts before Enumerable.Repeat.

Enumerable.Repeat(value, count) throws ArgumentOutOfRangeException when count < 0. The N1–N5 values come from database reads with NULL→0 conversion but no range validation. If the database contains corrupted negative counts, this refactor will crash instead of silently handling them. Clamp counts before calling Enumerable.Repeat():

Proposed fix
-        if (n1 + n2 + n3 + n4 + n5 == 0) return null;
-
-        var responses = Enumerable.Repeat(1m, n1)
-            .Concat(Enumerable.Repeat(2m, n2))
-            .Concat(Enumerable.Repeat(3m, n3))
-            .Concat(Enumerable.Repeat(4m, n4))
-            .Concat(Enumerable.Repeat(5m, n5))
+        n1 = Math.Max(0, n1);
+        n2 = Math.Max(0, n2);
+        n3 = Math.Max(0, n3);
+        n4 = Math.Max(0, n4);
+        n5 = Math.Max(0, n5);
+
+        if (n1 + n2 + n3 + n4 + n5 == 0) return null;
+
+        var responses = Enumerable.Repeat(1m, n1)
+            .Concat(Enumerable.Repeat(2m, n2))
+            .Concat(Enumerable.Repeat(3m, n3))
+            .Concat(Enumerable.Repeat(4m, n4))
+            .Concat(Enumerable.Repeat(5m, n5))
             .ToList();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (n1 + n2 + n3 + n4 + n5 == 0) return null;
var responses = Enumerable.Repeat(1m, n1)
.Concat(Enumerable.Repeat(2m, n2))
.Concat(Enumerable.Repeat(3m, n3))
.Concat(Enumerable.Repeat(4m, n4))
.Concat(Enumerable.Repeat(5m, n5))
.ToList();
n1 = Math.Max(0, n1);
n2 = Math.Max(0, n2);
n3 = Math.Max(0, n3);
n4 = Math.Max(0, n4);
n5 = Math.Max(0, n5);
if (n1 + n2 + n3 + n4 + n5 == 0) return null;
var responses = Enumerable.Repeat(1m, n1)
.Concat(Enumerable.Repeat(2m, n2))
.Concat(Enumerable.Repeat(3m, n3))
.Concat(Enumerable.Repeat(4m, n4))
.Concat(Enumerable.Repeat(5m, n5))
.ToList();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/Areas/Effort/Services/MeritMultiYearService.cs` around lines 868 - 875,
The code builds the responses list using Enumerable.Repeat with n1..n5 but
doesn't validate those counts; negative counts will throw
ArgumentOutOfRangeException. Before calling Enumerable.Repeat (the block that
constructs responses), clamp or sanitize the n1, n2, n3, n4, n5 values to a
non-negative integer (e.g., Math.Max(0, nX) or a small helper NormalizeCount)
and then use those sanitized variables when creating responses so
Enumerable.Repeat(...) never receives a negative count.

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.

2 participants