Skip to content

Commit 60a68ef

Browse files
authored
Merge pull request #176 from ucdavis/quality/analyzer-bulk-cleanup
PR 3: chore(quality): mechanical analyzer-driven cleanup (453 files)
2 parents ead4375 + 282bb6d commit 60a68ef

450 files changed

Lines changed: 1492 additions & 1726 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Viper.sln.DotSettings

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=OptimizeUsings/@EntryIndexedValue">&lt;Profile name="OptimizeUsings"&gt;&lt;CSOptimizeUsings&gt;&lt;OptimizeUsings&gt;True&lt;/OptimizeUsings&gt;&lt;EmbraceInRegion&gt;False&lt;/EmbraceInRegion&gt;&lt;RegionName&gt;&lt;/RegionName&gt;&lt;/CSOptimizeUsings&gt;&lt;/Profile&gt;</s:String>
3+
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=ShortenReferences/@EntryIndexedValue">&lt;Profile name="ShortenReferences"&gt;&lt;CSShortenReferences&gt;True&lt;/CSShortenReferences&gt;&lt;/Profile&gt;</s:String>
4+
<s:String x:Key="/Default/CodeStyle/CodeCleanup/Profiles/=RemoveRedundancies/@EntryIndexedValue">&lt;Profile name="RemoveRedundancies"&gt;&lt;CSRemoveCodeRedundancies&gt;True&lt;/CSRemoveCodeRedundancies&gt;&lt;RemoveCodeRedundancies&gt;True&lt;/RemoveCodeRedundancies&gt;&lt;CSRemoveRedundantArgumentDefaultValues&gt;True&lt;/CSRemoveRedundantArgumentDefaultValues&gt;&lt;CSRemoveRedundantInitializers&gt;True&lt;/CSRemoveRedundantInitializers&gt;&lt;/Profile&gt;</s:String>
5+
</wpf:ResourceDictionary>

scripts/audit-resharper-regression.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// [--sarif inspect-report/inspect.sarif]
1313
// [--skip-scan]
1414
// [--staged]
15+
// [--exclude-rule <id> ...]
1516
//
1617
// --skip-scan reuses the SARIF from a prior `audit:resharper` run, useful in
1718
// CI where the full scan and the gate are split into separate steps so the
@@ -20,6 +21,11 @@
2021
// --staged filters findings to staged C# lines (`git diff --cached`) instead of
2122
// PR-diff lines. Pair with --skip-scan for fast iterative pre-commit checks
2223
// against an existing SARIF report.
24+
//
25+
// --exclude-rule adds a ReSharper rule id to skip (repeatable). The default
26+
// list covers rules known to misfire on ASP.NET Core / EF DTO patterns where
27+
// public surface looks unused to static analysis but is wired up at runtime
28+
// (JSON serialization, MVC model binding, Razor views, EF projections).
2329

2430
const fs = require("node:fs")
2531
const path = require("node:path")
@@ -34,8 +40,30 @@ const MAX_BUFFER_BYTES = 268_435_456
3440
// Cap how many findings we print per rule before summarising the rest.
3541
const MAX_FINDINGS_PER_RULE = 5
3642

43+
// Rules excluded by default because they fire false positives on the kinds of
44+
// public surface ASP.NET Core / EF wires up at runtime (DTO/binding/EF
45+
// projection types) or where ReSharper's NRT contract analysis disagrees
46+
// with Roslyn's flow analysis (EF nav-property dereferences after `?.`).
47+
const DEFAULT_EXCLUDED_RULES = new Set([
48+
"UnusedAutoPropertyAccessor.Global",
49+
"UnusedAutoPropertyAccessor.Local",
50+
"NotAccessedPositionalProperty.Local",
51+
"S3260", // SonarLint sealed-record rule, low actionable value here
52+
// ReSharper trusts the NRT annotation on EF nav properties (`Rotation` is
53+
// declared non-null with `null!` default), but Roslyn rightly insists on
54+
// `?.` because the runtime can produce null when Include() is missing.
55+
// Keep the runtime-safe `?.Nav?.Member` style and silence the ReSharper rule.
56+
"ConditionalAccessQualifierIsNonNullableAccordingToAPIContract",
57+
])
58+
3759
function parseArgs(argv) {
38-
const args = { base: "origin/main", sarif: DEFAULT_SARIF, skipScan: false, staged: false }
60+
const args = {
61+
base: "origin/main",
62+
sarif: DEFAULT_SARIF,
63+
skipScan: false,
64+
staged: false,
65+
excludedRules: new Set(DEFAULT_EXCLUDED_RULES),
66+
}
3967
const remaining = [...argv]
4068
while (remaining.length > 0) {
4169
const flag = remaining.shift()
@@ -47,6 +75,8 @@ function parseArgs(argv) {
4775
args.skipScan = true
4876
} else if (flag === "--staged") {
4977
args.staged = true
78+
} else if (flag === "--exclude-rule") {
79+
args.excludedRules.add(remaining.shift())
5080
} else {
5181
console.error(`Unknown arg: ${flag}`)
5282
process.exit(2)
@@ -130,7 +160,7 @@ function normalizeUri(uri) {
130160
return s
131161
}
132162

133-
function findRegressions(sarifPath, changedLines) {
163+
function findRegressions(sarifPath, changedLines, excludedRules) {
134164
const sarif = JSON.parse(fs.readFileSync(sarifPath, "utf8"))
135165
const results = sarif.runs?.[0]?.results ?? []
136166

@@ -142,6 +172,9 @@ function findRegressions(sarifPath, changedLines) {
142172
const regressions = []
143173
for (const r of results) {
144174
const ruleId = r.ruleId ?? "?"
175+
if (excludedRules.has(ruleId)) {
176+
continue
177+
}
145178
for (const loc of r.locations ?? []) {
146179
const uri = loc.physicalLocation?.artifactLocation?.uri
147180
const line = loc.physicalLocation?.region?.startLine
@@ -186,7 +219,11 @@ if (changed.size === 0) {
186219
process.exit(0)
187220
}
188221

189-
const regressions = findRegressions(args.sarif, changed)
222+
if (args.excludedRules.size > 0) {
223+
const sortedRules = [...args.excludedRules].toSorted()
224+
console.log(`Excluding ${sortedRules.length} rule(s) from gate: ${sortedRules.join(", ")}`)
225+
}
226+
const regressions = findRegressions(args.sarif, changed, args.excludedRules)
190227
if (regressions.length === 0) {
191228
console.log(`✅ No new ReSharper warnings at ${touchedLabel} lines.`)
192229
process.exit(0)

test/AsyncQueryable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using Microsoft.EntityFrameworkCore.Query;
21
using System.Linq.Expressions;
2+
using Microsoft.EntityFrameworkCore.Query;
33

44
namespace Viper.test
55
{

test/CTS/AssessmentControllerTest.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
using System.Net;
12
using Microsoft.AspNetCore.Mvc;
23
using Microsoft.EntityFrameworkCore.Infrastructure;
34
using Microsoft.EntityFrameworkCore.Storage;
45
using NSubstitute;
5-
using System.Net;
66
using Viper.Areas.CTS.Controllers;
77
using Viper.Areas.CTS.Models;
88
using Viper.Classes.SQLContext;
@@ -164,7 +164,7 @@ public async Task CreateStudentEpaCheck()
164164
context.Database.Returns(facadeSub);
165165

166166
var actrlAsFac = GetAssessmentController(SetupUsers.UserType.Faculty);
167-
var newEpa = new CreateUpdateStudentEpa()
167+
var newEpa = new CreateUpdateStudentEpa
168168
{
169169
EncounterDate = DateTime.Now,
170170
Comment = "A comment",
@@ -204,7 +204,7 @@ public async Task UpdateStudentEpaCheck()
204204
var encId1 = SetupAssessments.Encounters.First(e => e.EnteredBy == SetupUsers.facultyUser.AaudUserId).EncounterId;
205205
var encId2 = SetupAssessments.Encounters.First(e => e.EnteredBy != SetupUsers.facultyUser.AaudUserId).EncounterId;
206206

207-
var epa1 = new CreateUpdateStudentEpa()
207+
var epa1 = new CreateUpdateStudentEpa
208208
{
209209
EncounterId = encId1,
210210
EncounterDate = DateTime.Now,
@@ -214,7 +214,7 @@ public async Task UpdateStudentEpaCheck()
214214
ServiceId = 0,
215215
StudentId = SetupUsers.studentUser1.AaudUserId,
216216
};
217-
var epa2 = new CreateUpdateStudentEpa()
217+
var epa2 = new CreateUpdateStudentEpa
218218
{
219219
EncounterId = encId2,
220220
EncounterDate = DateTime.Now,
@@ -224,7 +224,7 @@ public async Task UpdateStudentEpaCheck()
224224
ServiceId = 0,
225225
StudentId = SetupUsers.studentUser1.AaudUserId,
226226
};
227-
var epa3 = new CreateUpdateStudentEpa()
227+
var epa3 = new CreateUpdateStudentEpa
228228
{
229229
EncounterId = 99999,
230230
EncounterDate = DateTime.Now,
@@ -258,7 +258,7 @@ private static bool IsForbidResult<T>(ActionResult<T> a)
258258
var forbidResult = a.Result as ForbidResult;
259259
if (result != null)
260260
{
261-
Assert.Equal((int)HttpStatusCode.Forbidden, result?.StatusCode);
261+
Assert.Equal((int)HttpStatusCode.Forbidden, result.StatusCode);
262262
}
263263
Assert.True(result != null || forbidResult != null);
264264

test/CTS/CompetencyBundleAssociationControllerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public CompetencyBundleAssociationControllerTest()
112112
public async Task GetCompetencyBundleAssociations_NoFilters_ReturnsOnlyUnbundledCompetencies()
113113
{
114114
// Act
115-
var result = await _controller.GetCompetencyBundleAssociations(null, null, null);
115+
var result = await _controller.GetCompetencyBundleAssociations();
116116

117117
// Assert
118118
var okResult = Assert.IsType<ActionResult<List<CompetencyBundleAssociationDto>>>(result);

test/CTS/SetupAssessments.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
1+
using MockQueryable.NSubstitute;
12
using NSubstitute;
2-
using System.Linq.Dynamic.Core;
33
using Viper.Areas.CTS.Services;
44
using Viper.Classes.SQLContext;
55
using Viper.Models.CTS;
6-
using MockQueryable.NSubstitute;
6+
using Viper.Models.VIPER;
77

88
namespace Viper.test.CTS
99
{
1010
internal static class SetupAssessments
1111
{
12-
public static readonly List<Encounter> Encounters = new List<Encounter>()
12+
public static readonly List<Encounter> Encounters = new List<Encounter>
1313
{
14-
new Encounter()
14+
new Encounter
1515
{
1616
EncounterId = 1,
1717
EnteredBy = SetupUsers.facultyUser.AaudUserId,
1818
EnteredOn = DateTime.Now,
1919
StudentUserId = SetupUsers.studentUser1.AaudUserId,
2020
EncounterType = (int)EncounterCreationService.EncounterType.Epa,
21-
Student = new Models.VIPER.Person()
21+
Student = new Person
2222
{
2323
FullName = SetupUsers.studentUser1.DisplayLastName + ", " + SetupUsers.studentUser1.DisplayFirstName,
2424
MailId = "",
2525
},
2626
EnteredByPerson = SetupPeople.GetPeople().Where(p => p.PersonId == SetupUsers.facultyUser.AaudUserId).FirstOrDefault(),
2727
ServiceId = 1,
2828
},
29-
new Encounter()
29+
new Encounter
3030
{
3131
EncounterId = 2,
3232
EnteredBy = SetupUsers.facultyUser.AaudUserId,
3333
EnteredOn = DateTime.Now,
3434
StudentUserId = SetupUsers.studentUser1.AaudUserId,
3535
EncounterType = (int)EncounterCreationService.EncounterType.Epa,
36-
Student = new Models.VIPER.Person()
36+
Student = new Person
3737
{
3838
FullName = SetupUsers.studentUser1.DisplayLastName + ", " + SetupUsers.studentUser1.DisplayFirstName,
3939
MailId = "",
4040
},
4141
EnteredByPerson = SetupPeople.GetPeople().Where(p => p.PersonId == SetupUsers.facultyUser.AaudUserId).FirstOrDefault(),
4242
ServiceId = 2,
4343
},
44-
new Encounter()
44+
new Encounter
4545
{
4646
EncounterId = 3,
4747
EnteredBy = SetupUsers.otherFacultyUser.AaudUserId,
4848
EnteredOn = DateTime.Now,
4949
StudentUserId = SetupUsers.studentUser2.AaudUserId,
5050
EncounterType = (int)EncounterCreationService.EncounterType.Epa,
51-
Student = new Models.VIPER.Person()
51+
Student = new Person
5252
{
5353
FullName = SetupUsers.studentUser2.DisplayLastName + ", " + SetupUsers.studentUser2.DisplayFirstName,
5454
MailId = "",
@@ -73,7 +73,7 @@ public static void SetupEncountersTable(VIPERContext context)
7373
.Do(callInfo =>
7474
{
7575
var e = callInfo.Arg<Encounter>();
76-
e.Student = new Models.VIPER.Person()
76+
e.Student = new Person
7777
{
7878
PersonId = e.StudentUserId,
7979
};

test/CTS/SetupPeople.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
using MockQueryable.NSubstitute;
12
using NSubstitute;
23
using Viper.Classes.SQLContext;
34
using Viper.Models.VIPER;
4-
using MockQueryable.NSubstitute;
55

66
namespace Viper.test.CTS
77
{

test/Classes/ApiResponseAttributeTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
13
using Microsoft.AspNetCore.Http;
24
using Microsoft.AspNetCore.Mvc;
35
using Microsoft.AspNetCore.Mvc.Abstractions;
46
using Microsoft.AspNetCore.Mvc.Filters;
57
using Microsoft.AspNetCore.Routing;
6-
using System.Text.Json;
7-
using System.Text.Json.Serialization;
88
using Viper.Classes;
99

1010
namespace Test.Classes

test/Classes/CustomAntiforgeryFilterTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
using System.Net;
12
using Microsoft.AspNetCore.Antiforgery;
23
using Microsoft.AspNetCore.Http;
34
using Microsoft.AspNetCore.Mvc;
45
using Microsoft.AspNetCore.Mvc.Abstractions;
56
using Microsoft.AspNetCore.Mvc.Filters;
67
using Microsoft.AspNetCore.Routing;
78
using NSubstitute;
8-
using System.Net;
99
using Viper.Classes;
1010

1111
namespace Test.Classes

test/ClinicalScheduler/ClinicalSchedulerContextTest.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.EntityFrameworkCore;
22
using Viper.Classes.SQLContext;
3+
using Viper.Models.ClinicalScheduler;
34

45
namespace Viper.test.ClinicalScheduler
56
{
@@ -81,7 +82,7 @@ public void ClinicalSchedulerContext_ServiceIgnoredPropertiesNotIncluded()
8182

8283
// Act
8384
using var context = new ClinicalSchedulerContext(options);
84-
var serviceEntityType = context.Model.FindEntityType(typeof(Viper.Models.ClinicalScheduler.Service));
85+
var serviceEntityType = context.Model.FindEntityType(typeof(Service));
8586

8687
// Assert - Verify that Encounters and Epas navigation properties are ignored
8788
Assert.NotNull(serviceEntityType);

0 commit comments

Comments
 (0)