Skip to content

Commit 9ebfefb

Browse files
committed
refactor(avalonia): move global suppressions to source files
Replace assembly-level global suppressions with targeted suppressions at the source level for better maintainability and minimal suppression scope. - Add RCS1194 suppressions to exception classes using primary constructors - Add CA2000 suppressions to methods creating HttpContent objects - Add JSV01 suppressions to LoadProgramResponse and internal JSON wrapper records - Delete ARMEmulator/GlobalSuppressions.cs - Keep test global suppressions unchanged
1 parent aba7416 commit 9ebfefb

File tree

5 files changed

+24
-16
lines changed

5 files changed

+24
-16
lines changed

avalonia-gui/ARMEmulator/GlobalSuppressions.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

avalonia-gui/ARMEmulator/Models/ApiModels.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Diagnostics.CodeAnalysis;
2+
13
namespace ARMEmulator.Models;
24

35
/// <summary>
@@ -8,6 +10,7 @@ public sealed record SessionInfo(string SessionId);
810
/// <summary>
911
/// Response from loading a program.
1012
/// </summary>
13+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "ImmutableArray acceptable for small API response collections")]
1114
public sealed record LoadProgramResponse(
1215
bool Success,
1316
ImmutableArray<ParseError> Errors,

avalonia-gui/ARMEmulator/Services/ApiClient.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics.CodeAnalysis;
12
using System.Net;
23
using System.Net.Http.Json;
34
using System.Text;
@@ -42,6 +43,7 @@ public async Task DestroySessionAsync(string sessionId, CancellationToken ct = d
4243

4344
// Program Loading
4445

46+
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpClient takes ownership and disposes content")]
4547
public async Task<LoadProgramResponse> LoadProgramAsync(string sessionId, string source, CancellationToken ct = default)
4648
{
4749
var content = new StringContent(source, Encoding.UTF8, "text/plain");
@@ -134,6 +136,7 @@ public async Task<ImmutableArray<SourceMapEntry>> GetSourceMapAsync(string sessi
134136

135137
// Breakpoints
136138

139+
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpClient takes ownership and disposes content")]
137140
public async Task AddBreakpointAsync(string sessionId, uint address, CancellationToken ct = default)
138141
{
139142
var request = new AddBreakpointRequest(address);
@@ -159,6 +162,7 @@ public async Task<ImmutableArray<uint>> GetBreakpointsAsync(string sessionId, Ca
159162

160163
// Watchpoints
161164

165+
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpClient takes ownership and disposes content")]
162166
public async Task<Watchpoint> AddWatchpointAsync(string sessionId, uint address, WatchpointType type, CancellationToken ct = default)
163167
{
164168
var request = new AddWatchpointRequest(address, type.ToString().ToLowerInvariant());
@@ -184,6 +188,7 @@ public async Task<ImmutableArray<Watchpoint>> GetWatchpointsAsync(string session
184188

185189
// Expression Evaluation
186190

191+
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpClient takes ownership and disposes content")]
187192
public async Task<uint> EvaluateExpressionAsync(string sessionId, string expression, CancellationToken ct = default)
188193
{
189194
var request = new EvaluateExpressionRequest(expression);
@@ -204,6 +209,7 @@ public async Task<uint> EvaluateExpressionAsync(string sessionId, string express
204209

205210
// Input
206211

212+
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "HttpClient takes ownership and disposes content")]
207213
public async Task SendStdinAsync(string sessionId, string data, CancellationToken ct = default)
208214
{
209215
var content = new StringContent(data, Encoding.UTF8, "text/plain");

avalonia-gui/ARMEmulator/Services/ApiExceptions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics.CodeAnalysis;
12
using System.Net;
23
using ARMEmulator.Models;
34

@@ -6,6 +7,7 @@ namespace ARMEmulator.Services;
67
/// <summary>
78
/// Base exception for all API-related errors.
89
/// </summary>
10+
[SuppressMessage("Design", "RCS1194:Implement exception constructors", Justification = "Uses custom constructor with domain-specific parameters")]
911
public class ApiException : Exception
1012
{
1113
/// <summary>HTTP status code if available.</summary>
@@ -21,6 +23,7 @@ public ApiException(string message, HttpStatusCode? statusCode = null, Exception
2123
/// <summary>
2224
/// Thrown when a session is not found or has expired.
2325
/// </summary>
26+
[SuppressMessage("Design", "RCS1194:Implement exception constructors", Justification = "Uses primary constructor with domain-specific parameters")]
2427
public sealed class SessionNotFoundException(string sessionId)
2528
: ApiException($"Session '{sessionId}' not found or expired", HttpStatusCode.NotFound)
2629
{
@@ -31,6 +34,7 @@ public sealed class SessionNotFoundException(string sessionId)
3134
/// <summary>
3235
/// Thrown when program loading fails due to parse or assembly errors.
3336
/// </summary>
37+
[SuppressMessage("Design", "RCS1194:Implement exception constructors", Justification = "Uses primary constructor with domain-specific parameters")]
3438
public sealed class ProgramLoadException(ImmutableArray<ParseError> errors)
3539
: ApiException($"Program failed to load: {errors.Length} error(s)", HttpStatusCode.BadRequest)
3640
{
@@ -41,12 +45,14 @@ public sealed class ProgramLoadException(ImmutableArray<ParseError> errors)
4145
/// <summary>
4246
/// Thrown when the backend is unreachable or not responding.
4347
/// </summary>
48+
[SuppressMessage("Design", "RCS1194:Implement exception constructors", Justification = "Uses primary constructor with domain-specific parameters")]
4449
public sealed class BackendUnavailableException(string message, Exception? inner = null)
4550
: ApiException(message, null, inner);
4651

4752
/// <summary>
4853
/// Thrown when an expression evaluation fails.
4954
/// </summary>
55+
[SuppressMessage("Design", "RCS1194:Implement exception constructors", Justification = "Uses primary constructor with domain-specific parameters")]
5056
public sealed class ExpressionEvaluationException(string expression, string error)
5157
: ApiException($"Failed to evaluate '{expression}': {error}", HttpStatusCode.BadRequest)
5258
{

avalonia-gui/ARMEmulator/Services/ApiJsonContext.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Diagnostics.CodeAnalysis;
12
using System.Text.Json.Serialization;
23
using ARMEmulator.Models;
34

@@ -39,11 +40,19 @@ internal sealed record AddWatchpointRequest(uint Address, string Type);
3940
internal sealed record EvaluateExpressionRequest(string Expression);
4041

4142
// Internal response wrapper types (moved from ApiClient.cs for source generator visibility)
43+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4244
internal sealed record ApiErrorResponse(string Error, ParseError[]? ParseErrors = null);
45+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4346
internal sealed record MemoryResponse(byte[] Data);
47+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4448
internal sealed record DisassemblyResponse(DisassemblyInstruction[] Instructions);
49+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4550
internal sealed record SourceMapResponse(SourceMapEntry[] Entries);
51+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4652
internal sealed record BreakpointsResponse(uint[] Breakpoints);
53+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4754
internal sealed record WatchpointsResponse(Watchpoint[] Watchpoints);
55+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4856
internal sealed record EvaluationResponse(uint Value);
57+
[SuppressMessage("Design", "JSV01:Member does not have value semantics", Justification = "Internal wrapper for JSON deserialization, immediately converted to ImmutableArray")]
4958
internal sealed record ExamplesResponse(ExampleInfo[] Examples);

0 commit comments

Comments
 (0)