Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up-to-date .NET code quality analyzers #6434

Merged
merged 12 commits into from
Nov 28, 2024

Conversation

huoyaoyuan
Copy link
Contributor

This is an overhaul from previous FxCop (#3007). Now the rules are shipped in-box with .NET SDK, with concept of mode/level, allowing to set aggressiveness of categories instead of enumerating them.

The analysis rules are grouped by aggressiveness of None < Default < Minimum < Recommended < All. I avoided None and All because they would impact critical/too flaky ones, and didn't involve rules with too much noise/high design impact.

The performance concern for inner loop should be low, since many analyzers are already running at suggestion level. If there's evidence of performance impact, we can set EnableNETAnalyzers to false in projects and pass true in CI.

@@ -23,7 +23,7 @@ public static void VerifyZeroDiagnostics(this GeneratorDriverRunResult runResult
.Where(d => d.Severity == DiagnosticSeverity.Error)
.ToArray();

if (compilationDiagnostics.Any() || generatorDiagnostics.Any())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see this rule as controversial. As a non-English speaker, Any() or !Any() is less readable for me comparing to length tests. I separated all changes with this rule in one commit, in case if you'd like to revert it.

Comment on lines -11 to -14
M:System.Char.ToLower(System.Char);char.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
M:System.Char.ToUpper(System.Char);char.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use char.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture.
M:System.String.ToLower();string.ToLower() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToLowerInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
M:System.String.ToUpper();string.ToUpper() changes behaviour depending on CultureInfo.CurrentCulture. Use string.ToUpperInvariant() instead. If wanting culture-sensitive behaviour, explicitly provide CultureInfo.CurrentCulture or use LocalisableString.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These are covered in CA1304.

@@ -28,7 +28,17 @@
<AdditionalFiles Include="$(MSBuildThisFileDirectory)CodeAnalysis\BannedSymbols.txt" />
</ItemGroup>
<PropertyGroup Label="Code Analysis">
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)CodeAnalysis\osu-framework.ruleset</CodeAnalysisRuleSet>
<AnalysisMode>Default</AnalysisMode>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I tested Recommended as baseline for every category, and revert to Default if there's too much noise or controversary.

@@ -121,7 +121,7 @@ protected void Filter()
private void performFilter()
{
string[] terms = (searchTerm ?? string.Empty).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
Copy link
Contributor

Choose a reason for hiding this comment

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

To avoid the unnecessary allocation. Not related to this PR, but noticed it while reading through it. Wanna include it in this PR while you are at it?
I'm surprised that there is no analyzer for this 😅

Suggested change
string[] terms = (searchTerm ?? string.Empty).Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
string[] terms = (searchTerm ?? string.Empty).Split(' ', StringSplitOptions.RemoveEmptyEntries);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah surprisingly, there isn't a single rule for switching from collection parameter to singleton. CA1861 is about using collections more efficiently.
I'd like to avoid including unrelated changes for this PR, because the discovered instance numbers can be non-trivial.

Copy link
Member

@Susko3 Susko3 left a comment

Choose a reason for hiding this comment

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

More care needs to be given when changing ContainsKey() & item access to TryGetValue(). I assume you've just run an automatic fixer?

Due the to currently chosen code structure and variable names, it's harder to understand than the original code.

@@ -545,10 +545,11 @@ protected override IEnumerable<Vector2> ComputeLayoutPositions()

private void updateChildIfNeeded(TabItem<T> child, bool isVisible)
{
if (!tabVisibility.ContainsKey(child) || tabVisibility[child] != isVisible)
if (!tabVisibility.TryGetValue(child, out bool value) || value != isVisible)
Copy link
Member

Choose a reason for hiding this comment

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

Please don't name it value. Maybe currentVisibility?

Comment on lines 551 to 552
tabVisibility[child] = isVisible;
value = isVisible;
tabVisibility[child] = value;
Copy link
Member

Choose a reason for hiding this comment

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

Just revert this change, it doesn't really make sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code fixer was too dumb to include this

Comment on lines 185 to 188
if (!runningStatus.TryGetValue(senderId, out byte value))
throw new InvalidDataException($"Received running status of sender {senderId}, but no event type was stored");

eventType = runningStatus[senderId];
eventType = value;
Copy link
Member

Choose a reason for hiding this comment

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

-if (!runningStatus.TryGetValue(senderId, out byte value))
+if (!runningStatus.TryGetValue(senderId, out eventType))

@huoyaoyuan
Copy link
Contributor Author

I assume you've just run an automatic fixer?

Correct. I didn't even look through the code in detail since the fix is quite mature.

@peppy peppy self-requested a review November 28, 2024 04:35
Copy link
Member

@peppy peppy left a comment

Choose a reason for hiding this comment

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

No issues from my end 👍

Copy link
Contributor

@smoogipoo smoogipoo left a comment

Choose a reason for hiding this comment

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

Seems ok

@peppy peppy merged commit 0c99586 into ppy:master Nov 28, 2024
13 of 14 checks passed
@huoyaoyuan huoyaoyuan deleted the netcode-codeanalysis branch November 28, 2024 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants