Skip to content

Commit

Permalink
Upgrade MudBlazor (Minor) + Meziantou.Analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
chklauser committed Jun 8, 2024
1 parent 16310e3 commit 9752a52
Show file tree
Hide file tree
Showing 23 changed files with 99 additions and 46 deletions.
28 changes: 28 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# noinspection EditorConfigKeyCorrectness
[*.{cs,cshtml,razor}]
# MA0048: File may only contain a single top-level type
dotnet_diagnostic.MA0048.severity = none

# MA0008: Structs must have struct layout
dotnet_diagnostic.MA0008.severity = none

# MA0006: Use string.Equals instead of ==
dotnet_diagnostic.MA0006.severity = none

# MA0004: synchronization context (always needed in Blazor)
dotnet_diagnostic.MA0004.severity = none

# MA0015 - Specify the parameter name in ArgumentException
dotnet_diagnostic.MA0015.severity = none

# MA0051 - Method is too long
dotnet_diagnostic.MA0051.severity = none
# MA0051.maximum_lines_per_method = 60
# MA0051.maximum_statements_per_method = 40
# MA0051.skip_local_functions = false # skip local functions when counting statements

# MA0045 - sync in async
dotnet_diagnostic.MA0045.severity = info

# MA0080 - cancellation token AsyncEnumerable iteration
dotnet_diagnostic.MA0080.severity = info
10 changes: 7 additions & 3 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="8.0.0" />
<PackageVersion Include="Microsoft.Identity.Web" Version="2.16.0" />
<PackageVersion Include="Microsoft.Identity.Web.UI" Version="2.16.0" />
<PackageVersion Include="MudBlazor" Version="6.15.0" />
<PackageVersion Include="Microsoft.Identity.Web" Version="2.19.0" />
<PackageVersion Include="Microsoft.Identity.Web.UI" Version="2.19.0" />
<PackageVersion Include="MudBlazor" Version="6.20.0" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
<PackageVersion Include="RavenDB.Client" Version="6.0.103" />
<PackageVersion Include="RavenDB.Embedded" Version="6.0.103" />
Expand All @@ -36,5 +36,9 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.742">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
9 changes: 5 additions & 4 deletions Splitracker.Domain/ActionShorthand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Splitracker.Domain;
Expand Down Expand Up @@ -95,19 +96,19 @@ public int Roll(Random random)
return null;
}

if (m.Groups["const"] is { Success: true, ValueSpan: var rawConst } && int.TryParse(rawConst, out var @const))
if (m.Groups["const"] is { Success: true, ValueSpan: var rawConst } && int.TryParse(rawConst, provider: CultureInfo.InvariantCulture, out var @const))
{
return new(0, 0, @const);
}

var numDice =
m.Groups["numd"] is { Success: true, ValueSpan: var rawNumDice } &&
int.TryParse(rawNumDice, out var parsedNumDice)
int.TryParse(rawNumDice, provider: CultureInfo.InvariantCulture, out var parsedNumDice)
? parsedNumDice
: 1;
var numSides =
m.Groups["nums"] is { Success: true, ValueSpan: var rawNumSides } &&
int.TryParse(rawNumSides, out var parsedNumSides)
int.TryParse(rawNumSides, provider: CultureInfo.InvariantCulture, out var parsedNumSides)
? parsedNumSides
: 6;
var sign =
Expand All @@ -116,7 +117,7 @@ public int Roll(Random random)
: 1;
var bonus =
m.Groups["bonus"] is { Success: true, ValueSpan: var rawBonus } &&
int.TryParse(rawBonus, out var parsedBonus)
int.TryParse(rawBonus, provider: CultureInfo.InvariantCulture, out var parsedBonus)
? parsedBonus * sign
: 0;

Expand Down
2 changes: 2 additions & 0 deletions Splitracker.Domain/Group.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ public record Group(

public record GroupMembership(string UserId, GroupRole Role);

#pragma warning disable MA0048
public enum GroupRole
#pragma warning restore MA0048
{
Member,
GameMaster,
Expand Down
5 changes: 4 additions & 1 deletion Splitracker.Domain/NameGenerationService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -53,7 +54,9 @@ public INamingScheme InferNamingScheme(IEnumerable<string> names)
static (string Name, Scheme? Scheme, int Parsed) parsed(string name)
{
var match = suffixPattern().Match(name);
if (match.Groups["num"] is { Success: true } num && int.TryParse(num.ValueSpan, out var parsed))
if (match.Groups["num"] is { Success: true } num && int.TryParse(num.ValueSpan,
provider: CultureInfo.InvariantCulture,
out var parsed))
{
return (name, Scheme.Number, parsed);
}
Expand Down
3 changes: 2 additions & 1 deletion Splitracker.Domain/PointsVec.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Splitracker.Domain;
Expand Down Expand Up @@ -87,7 +88,7 @@ public static PointsVec From(ReadOnlySpan<char> input, PointType defaultType)
currentType = PointType.V;
break;
default:
if (int.TryParse(input.Slice(match.Index, match.Length), out var numericValue))
if (int.TryParse(input.Slice(match.Index, match.Length), provider: CultureInfo.InvariantCulture, out var numericValue))
{
vec = currentType switch
{
Expand Down
8 changes: 5 additions & 3 deletions Splitracker.Persistence/Characters/RavenCharacterHandle.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using Splitracker.Domain;
using System.Diagnostics.CodeAnalysis;
using Splitracker.Domain;
using Splitracker.Persistence.Generic;

namespace Splitracker.Persistence.Characters;

/// <summary>
/// Mutable container for a <see cref="Character"/>. Triggers the <see cref="Updated"/> event whenever
/// Mutable container for a <see cref="Character"/>. Triggers the <c>Updated</c> event whenever
/// anything about the character changes.
/// </summary>
class RavenCharacterHandle(Character character)
[SuppressMessage("Design", "MA0095:A class that implements IEquatable<T> should override Equals(object)")]
sealed class RavenCharacterHandle(Character character)
: PrefixHandleBase<RavenCharacterHandle, Character>(character),
IPrefixHandle<RavenCharacterHandle, Character>,
ICharacterHandle
Expand Down
12 changes: 6 additions & 6 deletions Splitracker.Persistence/Characters/RavenCharacterRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ NameGenerationService nameGeneration
{
internal const string CollectionName = "Characters";

readonly ConcurrentDictionary<string, Task<RavenCharacterRepositorySubscription>> handles = new();
readonly ConcurrentDictionary<string, Task<RavenCharacterRepositorySubscription>> handles = new(StringComparer.Ordinal);

bool isOwner(string characterId, string userId) =>
characterId.StartsWith(CharacterDocIdPrefix(userId), StringComparison.Ordinal);
Expand Down Expand Up @@ -261,7 +261,7 @@ void stopChanneling(Pool model, Domain.Pool domain, string channelingId)
.ToListAsync();
var baseName = nameGeneration.InferTemplateName(model.Name);
var scheme = nameGeneration.InferNamingScheme(relatedNames ?? []);
newInstanceName = scheme.GenerateNext().Replace("\uFFFC", baseName);
newInstanceName = scheme.GenerateNext().Replace("\uFFFC", baseName, StringComparison.Ordinal);
}
else
{
Expand Down Expand Up @@ -320,7 +320,7 @@ public async Task ApplyAsync(ClaimsPrincipal principal, DeleteTag deleteTagComma
var affectedCharacters = await session.Query<Character>()
.Where(c =>
c.Id.StartsWith(CharacterDocIdPrefix(userId))
&& c.TagIds.Contains(deleteTagCommand.TagId))
&& c.TagIds.Contains(deleteTagCommand.TagId, StringComparer.Ordinal))
.ToListAsync();
foreach (var character in affectedCharacters)
{
Expand Down Expand Up @@ -358,7 +358,7 @@ static IAsyncDocumentQuery<Character> byNameSearch(IAsyncDocumentSession session

internal static async Task<IReadOnlyDictionary<string, Character>> FetchTemplatesAsync(IAsyncDocumentSession session, IEnumerable<Character> characters)
{
var templateIds = characters.Select(c => c.TemplateId).OfType<string>().ToHashSet();
var templateIds = characters.Select(c => c.TemplateId).OfType<string>().ToHashSet(StringComparer.Ordinal);
if (templateIds.Count == 0)
{
return ImmutableDictionary<string, Character>.Empty;
Expand Down Expand Up @@ -390,12 +390,12 @@ public async Task<ICharacterRepositoryHandle> OpenAsync(ClaimsPrincipal principa
) ?? throw new InvalidOperationException("Failed to open a handle.");
}

readonly ConcurrentDictionary<string, Task<RavenSingleCharacterSubscription>> singleHandles = new();
readonly ConcurrentDictionary<string, Task<RavenSingleCharacterSubscription>> singleHandles = new(StringComparer.Ordinal);

public async Task<ICharacterHandle?> OpenSingleAsync(ClaimsPrincipal principal, string characterId)
{
var userId = await repository.GetUserIdAsync(principal);
if (!characterId.StartsWith(CharacterDocIdPrefix(userId)))
if (!characterId.StartsWith(CharacterDocIdPrefix(userId), StringComparison.Ordinal))
{
return null;
}
Expand Down
4 changes: 3 additions & 1 deletion Splitracker.Persistence/Generic/HandleBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace Splitracker.Persistence.Generic;
Expand All @@ -8,12 +9,13 @@ abstract class HandleBase<TSubscription, TValue> : IAsyncDisposable, IDisposable
{
readonly TSubscription subscription;

public HandleBase(TSubscription subscription)
protected HandleBase(TSubscription subscription)
{
this.subscription = subscription;
subscription.Updated += OnUpdated;
}

[SuppressMessage("Usage", "MA0091:Sender should be \'this\' for instance events")]
void OnUpdated(object? sender, EventArgs e)
{
Updated?.Invoke(sender, e);
Expand Down
4 changes: 3 additions & 1 deletion Splitracker.Persistence/Generic/PrefixHandleBase.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Diagnostics.CodeAnalysis;

namespace Splitracker.Persistence.Generic;

[SuppressMessage("Design", "MA0077:A class that provides Equals(T) should implement IEquatable<T>")]
abstract class PrefixHandleBase<TSelf, TValue>(TValue value) : IDisposable, IEquatable<TSelf>
where TSelf : PrefixHandleBase<TSelf, TValue>
where TValue : class
Expand Down Expand Up @@ -47,7 +49,7 @@ public override bool Equals(object? obj)

public override int GetHashCode()
{
return Id.GetHashCode();
return Id.GetHashCode(StringComparison.Ordinal);
}

public static bool operator ==(PrefixHandleBase<TSelf, TValue>? left, PrefixHandleBase<TSelf, TValue>? right)
Expand Down
5 changes: 4 additions & 1 deletion Splitracker.Persistence/Generic/PrefixRepositoryHandle.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace Splitracker.Persistence.Generic;
Expand All @@ -9,7 +10,7 @@ abstract class PrefixRepositoryHandle<TSelf, TSubscription> : IAsyncDisposable,
{
protected readonly TSubscription Subscription;

public PrefixRepositoryHandle(TSubscription subscription)
protected PrefixRepositoryHandle(TSubscription subscription)
{
Subscription = subscription;
subscription.Added += OnAdded;
Expand All @@ -19,11 +20,13 @@ public PrefixRepositoryHandle(TSubscription subscription)
public event EventHandler? Added;
public event EventHandler? Deleted;

[SuppressMessage("Usage", "MA0091:Sender should be \'this\' for instance events")]
void OnAdded(object? sender, EventArgs e)
{
Added?.Invoke(sender, e);
}

[SuppressMessage("Usage", "MA0091:Sender should be \'this\' for instance events")]
void OnDeleted(object? sender, EventArgs e)
{
Deleted?.Invoke(sender, e);
Expand Down
8 changes: 4 additions & 4 deletions Splitracker.Persistence/Generic/SubscriptionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ abstract class SubscriptionBase<TSelf, TValue, THandle> : IDisposable, ISubscrip
bool lifetimeBoundToHandles;
IImmutableDictionary<string, IDisposable> ravenSubscriptions;

public SubscriptionBase(ILogger log, TValue initialValue, IDocumentStore store, IEnumerable<string> documentIdsToSubscribeTo)
protected SubscriptionBase(ILogger log, TValue initialValue, IDocumentStore store, IEnumerable<string> documentIdsToSubscribeTo)
{
Log = log;
Store = store;
CurrentValue = initialValue;
ravenSubscriptions = documentIdsToSubscribeTo
.Distinct()
.Distinct(StringComparer.Ordinal)
.ToImmutableDictionary(
id => id,
id => store.Changes().ForDocument(id).Subscribe(this)
Expand Down Expand Up @@ -148,9 +148,9 @@ void synchronizeSubscriptions(TValue value)
try
{
var existingSubscriptions = ravenSubscriptions;
var existingKeys = existingSubscriptions.Keys.ToHashSet();
var existingKeys = existingSubscriptions.Keys.ToHashSet(StringComparer.Ordinal);
var requiredKeys = DocumentIdsToSubscribeToFor(value)
.ToHashSet();
.ToHashSet(StringComparer.Ordinal);
foreach (var key in requiredKeys.ToList())
{
if (existingKeys.Remove(key))
Expand Down
10 changes: 5 additions & 5 deletions Splitracker.Persistence/Groups/RavenGroupRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IUserRepository repository

#region Reading

readonly ConcurrentDictionary<string, Task<RavenGroupSubscription>> handles = new();
readonly ConcurrentDictionary<string, Task<RavenGroupSubscription>> handles = new(StringComparer.Ordinal);

public async Task<IGroupHandle?> OpenSingleAsync(ClaimsPrincipal principal, string groupId)
{
Expand Down Expand Up @@ -157,7 +157,7 @@ public async Task JoinWithExistingCharacterAsync(ClaimsPrincipal principal, Doma
{
var userId = await repository.GetUserIdAsync(principal);

if (!character.Id.StartsWith(RavenCharacterRepository.CharacterDocIdPrefix(userId)))
if (!character.Id.StartsWith(RavenCharacterRepository.CharacterDocIdPrefix(userId), StringComparison.Ordinal))
{
throw new DataAccessControlException(character.Id, userId);
}
Expand Down Expand Up @@ -218,7 +218,7 @@ async Task joinGroupAsync(string groupId, string userId, string characterId, IAs
group.Members.Add(new() { UserId = userId, Role = Model.GroupRole.Member });
}

if (group.CharacterIds.Contains(characterId))
if (group.CharacterIds.Contains(characterId, StringComparer.Ordinal))
{
log.Log(LogLevel.Warning, "Character {CharacterId} is already a member of group {GroupId}", characterId, groupId);
}
Expand Down Expand Up @@ -246,7 +246,7 @@ public async Task LeaveGroupAsync(ClaimsPrincipal principal, Domain.Group group,
throw new DataAccessControlException("User is not a member of the group.", group.Id, userId);
}

if (role != Model.GroupRole.GameMaster && !character.Id.StartsWith(characterDocIdPrefix))
if (role != Model.GroupRole.GameMaster && !character.Id.StartsWith(characterDocIdPrefix, StringComparison.Ordinal))
{
throw new DataAccessControlException($"User is not allowed to remove character {character.Id} from group.", group.Id, userId);
}
Expand All @@ -270,7 +270,7 @@ void enforceGroupInvariants(Model.Group dbGroup)
{
// List of character IDs does not contain duplicates
var characterIds = dbGroup.CharacterIds;
if (characterIds.Count != characterIds.Distinct().Count())
if (characterIds.Count != characterIds.Distinct(StringComparer.Ordinal).Count())
{
throw new InvalidOperationException(
$"Group {dbGroup.Id} has duplicate character IDs in list of characters.");
Expand Down
4 changes: 2 additions & 2 deletions Splitracker.Persistence/Model/CharacterModelMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ public static Domain.Character ToDomain(this Character model, Character? templat
var template = templateModel?.ToDomain((Character?)null) ?? Prototype;
var actionShorthands = model.ActionShorthands
.Select(s => s.ToDomain())
.ToDictionary(s => s.Id);
.ToDictionary(s => s.Id, comparer: StringComparer.Ordinal);
foreach (var templateActionShorthand in template.ActionShorthands.Values)
{
actionShorthands.TryAdd(templateActionShorthand.Id, templateActionShorthand);
}

return new(model.Id,
model.Name.Replace("\uFFFC", template.Name),
model.Name.Replace("\uFFFC", template.Name, StringComparison.Ordinal),
model.CustomColor ?? template.CustomColor,
model.Lp.ToDomainLp(template.Lp.BaseCapacity),
model.Fo.ToDomainFo(template.Fo.BaseCapacity),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ internal static void CustomizeStore(IDocumentStore store)
store.Conventions.FindCollectionName = type =>
{
var defaultName = DocumentConventions.DefaultGetCollectionName(type);
return defaultName.EndsWith("Models") ? $"{defaultName[..^6]}s" : defaultName;
return defaultName.EndsWith("Models", StringComparison.Ordinal) ? $"{defaultName[..^6]}s" : defaultName;
};
}

Expand Down
2 changes: 2 additions & 0 deletions Splitracker.Persistence/RavenOptions.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;

namespace Splitracker.Persistence;

[UsedImplicitly(ImplicitUseTargetFlags.Itself)]
[SuppressMessage("Design", "MA0016:Prefer returning collection abstraction instead of implementation")]
public class RavenOptions
{
[Required]
Expand Down
Loading

0 comments on commit 9752a52

Please sign in to comment.