Some more analyzer cleanup (#815)

This commit is contained in:
Stephen Toub
2025-09-22 09:20:32 -04:00
committed by GitHub
Unverified
parent c587103753
commit c5e6735b7a
42 changed files with 100 additions and 153 deletions
+19 -16
View File
@@ -137,7 +137,6 @@ dotnet_diagnostic.IDE0005.severity = warning # Remove unnecessary using directiv
dotnet_diagnostic.IDE0009.severity = warning # Add this or Me qualification
dotnet_diagnostic.IDE0011.severity = warning # Add braces
dotnet_diagnostic.IDE0018.severity = warning # Inline variable declaration
dotnet_diagnostic.IDE0032.severity = warning # Use auto-implemented property
dotnet_diagnostic.IDE0034.severity = warning # Simplify 'default' expression
dotnet_diagnostic.IDE0035.severity = warning # Remove unreachable code
@@ -153,8 +152,9 @@ dotnet_diagnostic.IDE0073.severity = warning # Require file header
dotnet_diagnostic.IDE0082.severity = warning # Convert typeof to nameof
dotnet_diagnostic.IDE0090.severity = warning # Simplify new expression
dotnet_diagnostic.IDE0161.severity = warning # Use file-scoped namespace
dotnet_diagnostic.IDE0280.severity = warning # Use nameof
dotnet_diagnostic.VSTHRD111.severity = error # Use .ConfigureAwait(bool)
dotnet_diagnostic.VSTHRD111.severity = warning # Use .ConfigureAwait(bool)
dotnet_diagnostic.VSTHRD200.severity = warning # Use Async suffix for async methods
dotnet_diagnostic.RCS1021.severity = warning # Use expression-bodied lambda.
@@ -175,20 +175,21 @@ dotnet_diagnostic.RCS1201.severity = warning # Use method chaining.
dotnet_diagnostic.IDE0001.severity = warning # Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify member access
dotnet_diagnostic.IDE0004.severity = warning # Remove unnecessary cast
dotnet_diagnostic.IDE0032.severity = warning # Use auto property
dotnet_diagnostic.IDE0035.severity = warning # Remove unreachable code
dotnet_diagnostic.IDE0047.severity = warning # Parentheses can be removed
dotnet_diagnostic.IDE0051.severity = warning # Remove unused private member
dotnet_diagnostic.IDE0052.severity = warning # Remove unread private member
dotnet_diagnostic.IDE0059.severity = warning # Unnecessary assignment of a value
dotnet_diagnostic.IDE0110.severity = warning # Remove unnecessary discards
dotnet_diagnostic.IDE0032.severity = warning # Use auto property
dotnet_diagnostic.IDE0047.severity = warning # Parentheses can be removed
dotnet_diagnostic.IDE1006.severity = error # Naming rule violations
dotnet_diagnostic.IDE1006.severity = warning # Naming rule violations
# Suppressed diagnostics
dotnet_diagnostic.CA1002.severity = none # Change 'List<string>' in '...' to use 'Collection<T>' ...
dotnet_diagnostic.CA1031.severity = none # Do not catch general exception types
dotnet_diagnostic.CA1032.severity = none # We're using RCS1194 which seems to cover more ctors
dotnet_diagnostic.CA1034.severity = none # Do not nest type. Alternatively, change its accessibility so that it is not externally visible
dotnet_diagnostic.CA1054.severity = none # Uri parameters should not be strings
dotnet_diagnostic.CA1062.severity = none # Disable null check, C# already does it for us
dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters
dotnet_diagnostic.CA1305.severity = none # Operation could vary based on current user's locale settings
@@ -197,12 +198,13 @@ dotnet_diagnostic.CA1508.severity = none # Avoid dead conditional code. Too many
dotnet_diagnostic.CA1510.severity = none # ArgumentNullException.Throw
dotnet_diagnostic.CA1512.severity = none # ArgumentOutOfRangeException.Throw
dotnet_diagnostic.CA1515.severity = none # Making public types from exes internal
dotnet_diagnostic.CA1846.severity = none # Prefer 'AsSpan' over 'Substring'
dotnet_diagnostic.CA1848.severity = none # For improved performance, use the LoggerMessage delegates
dotnet_diagnostic.CA1849.severity = none # Use async equivalent; analyzer is currently noisy
dotnet_diagnostic.CA1865.severity = none # StartsWith(char)
dotnet_diagnostic.CA1867.severity = none # EndsWith(char)
dotnet_diagnostic.CS1998.severity = none # async method lacks 'await' operators and will run synchronously
dotnet_diagnostic.CA2000.severity = suggestion # Call System.IDisposable.Dispose on object before all references to it are out of scope
dotnet_diagnostic.CA2000.severity = none # Call System.IDisposable.Dispose on object before all references to it are out of scope
dotnet_diagnostic.CA2225.severity = none # Operator overloads have named alternates
dotnet_diagnostic.CA2227.severity = none # Change to be read-only by removing the property setter
dotnet_diagnostic.CA2253.severity = none # Named placeholders in the logging message template should not be comprised of only numeric characters
@@ -213,7 +215,9 @@ dotnet_diagnostic.CA5394.severity = none # Do not use insecure sources of random
dotnet_diagnostic.VSTHRD003.severity = none # Waiting on thread from another context
dotnet_diagnostic.VSTHRD103.severity = none # Use async equivalent; analyzer is currently noisy
dotnet_diagnostic.VSTHRD111.severity = none # Use .ConfigureAwait(bool) is hidden by default, set to none to prevent IDE from changing on autosave
dotnet_diagnostic.xUnit1004.severity = none # Test methods should not be skipped. Remove the Skip property to start running the test again.
dotnet_diagnostic.xUnit1042.severity = none # Untyped data rows
dotnet_diagnostic.RCS1032.severity = none # Remove redundant parentheses.
dotnet_diagnostic.RCS1074.severity = none # Remove redundant constructor.
@@ -234,29 +238,28 @@ dotnet_diagnostic.RCS1226.severity = none # Add paragraph to documentation comme
dotnet_diagnostic.RCS1229.severity = none # Use async/await when necessary.
dotnet_diagnostic.RCS1234.severity = none # Enum duplicate value
dotnet_diagnostic.RCS1238.severity = none # Avoid nested ?: operators.
dotnet_diagnostic.RCS1241.severity = none # Implement IComparable when implementing IComparable<T><T>.
dotnet_diagnostic.RCS1241.severity = none # Implement IComparable when implementing IComparable<T>
dotnet_diagnostic.RCS1246.severity = none # Use element access
dotnet_diagnostic.RCS1261.severity = none # Resource can be disposed asynchronously
dotnet_diagnostic.IDE0010.severity = none # Populate switch
dotnet_diagnostic.IDE0021.severity = none # Use block body for constructors
dotnet_diagnostic.IDE0022.severity = none # Use block body for methods
dotnet_diagnostic.IDE0024.severity = none # Use block body for operator
dotnet_diagnostic.IDE0058.severity = none # Remove unused expression value
dotnet_diagnostic.IDE0042.severity = none # Variable declaration can be deconstructed
dotnet_diagnostic.IDE0046.severity = none # if statement can be simplified
dotnet_diagnostic.IDE0056.severity = none # Indexing can be simplified
dotnet_diagnostic.IDE0057.severity = none # Substring can be simplified
dotnet_diagnostic.IDE0060.severity = none # Remove unused parameter
dotnet_diagnostic.IDE0061.severity = none # Use block body for local function
dotnet_diagnostic.IDE0079.severity = none # Remove unnecessary suppression.
dotnet_diagnostic.IDE0080.severity = none # Remove unnecessary suppression operator.
dotnet_diagnostic.IDE0100.severity = none # Remove unnecessary equality operator
dotnet_diagnostic.IDE0130.severity = none # Namespace does not match folder structure
dotnet_diagnostic.IDE0290.severity = none # Use primary constructor
dotnet_diagnostic.IDE0160.severity = none # Use block-scoped namespace
dotnet_diagnostic.IDE1006.severity = warning # Naming rule violations
dotnet_diagnostic.IDE0042.severity = none # Variable declaration can be deconstructed
dotnet_diagnostic.IDE0046.severity = suggestion # If statement can be simplified
dotnet_diagnostic.IDE0056.severity = suggestion # Indexing can be simplified
dotnet_diagnostic.IDE0057.severity = suggestion # Substring can be simplified
dotnet_diagnostic.IDE0079.severity = none # Remove unnecessary suppression
dotnet_diagnostic.IDE0290.severity = none # Use primary constructor
dotnet_diagnostic.IDE0046.severity = none # if statement can be simplified
dotnet_diagnostic.IDE0305.severity = none # ToList can be simplified
dotnet_diagnostic.IDE0330.severity = none # Use 'System.Threading.Lock'
# Testing
dotnet_diagnostic.Moq1400.severity = none # Explicitly choose a mocking behavior instead of relying on the default (Loose) behavior
@@ -115,7 +115,7 @@ public static class ModelExtensions
new("ConnectionString", csTask.Result ) { IsSensitive = true }
]
});
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
#pragma warning restore VSTHRD002
}
builder.Resource.UnderlyingResource = builder.Resource;
@@ -175,7 +175,7 @@ public static class ModelExtensions
new("ConnectionString", csTask.Result ) { IsSensitive = true }
]
});
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
#pragma warning restore VSTHRD002
}
builder.Resource.UnderlyingResource = builder.Resource;
@@ -214,7 +214,7 @@ public static class ModelExtensions
new("ConnectionString", csTask.Result ) { IsSensitive = true }
]
});
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
#pragma warning restore VSTHRD002
}
builder.Resource.UnderlyingResource = builder.Resource;
@@ -37,7 +37,7 @@
<option value="@agent.Name">@GetAgentDisplayName(agent.Name!) - @agent.Description</option>
}
</select>
@if (!string.IsNullOrEmpty(selectedAgentName) && currentConversation == null)
@if (!string.IsNullOrEmpty(selectedAgentName) && currentConversation is null)
{
<button class="start-chat-btn" @onclick="StartNewConversation">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -117,7 +117,7 @@
}
</div>
@if (discoveredAgentCardJson != null)
@if (discoveredAgentCardJson is not null)
{
<div class="agent-card-display">
<h4 class="card-title">🔗 Discovered Agent Card</h4>
@@ -173,7 +173,7 @@
</div>
}
@if (currentConversation != null)
@if (currentConversation is not null)
{
<div class="chat-container">
<div class="chat-messages" id="chat-messages">
@@ -1011,7 +1011,7 @@
private void SelectConversation(string sessionId)
{
currentConversation = conversations.FirstOrDefault(c => c.SessionId == sessionId);
if (currentConversation != null)
if (currentConversation is not null)
{
selectedAgentName = currentConversation.AgentName;
Logger.LogDebug("Selected conversation with session: {SessionId}", sessionId);
@@ -1022,14 +1022,14 @@
private void CloseConversation(string sessionId)
{
var conversationToRemove = conversations.FirstOrDefault(c => c.SessionId == sessionId);
if (conversationToRemove != null)
if (conversationToRemove is not null)
{
conversations.Remove(conversationToRemove);
if (currentConversation?.SessionId == sessionId)
{
currentConversation = conversations.FirstOrDefault();
if (currentConversation != null)
if (currentConversation is not null)
{
selectedAgentName = currentConversation.AgentName;
}
@@ -1042,7 +1042,7 @@
private async Task SendMessage()
{
if (string.IsNullOrWhiteSpace(currentMessage) || isStreaming || currentConversation == null)
if (string.IsNullOrWhiteSpace(currentMessage) || isStreaming || currentConversation is null)
return;
var userMessage = currentMessage.Trim();
@@ -56,9 +56,9 @@ async Task SKAgentAsync()
{
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
}
#pragma warning restore SKEXP0110
}
}
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
// Clean up
await thread.DeleteAsync();
@@ -60,9 +60,9 @@ async Task SKAgentAsync()
{
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
}
#pragma warning restore SKEXP0110
}
}
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
// Clean up
await thread.DeleteAsync();
@@ -47,9 +47,7 @@ internal sealed class ExperimentalAttribute : Attribute
/// </summary>
/// <value>The format string that represents a URL to corresponding documentation.</value>
/// <remarks>An example format string is <c>https://contoso.com/obsoletion-warnings/{0}</c>.</remarks>
#pragma warning disable S3996 // URI properties should not be strings
public string? UrlFormat { get; set; }
#pragma warning restore S3996 // URI properties should not be strings
}
#endif
@@ -221,10 +221,10 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
QuestionExecutor questionExecutor = new(item, this._workflowState);
this.ContinueWith(questionExecutor);
this._workflowModel.AddLink(actionId, postId, message => questionExecutor.IsComplete(message));
this._workflowModel.AddLink(actionId, postId, QuestionExecutor.IsComplete);
string prepareId = QuestionExecutor.Steps.Prepare(actionId);
this.ContinueWith(new DelegateActionExecutor(prepareId, this._workflowState, questionExecutor.PrepareResponseAsync, emitResult: false), parentId, message => !questionExecutor.IsComplete(message));
this.ContinueWith(new DelegateActionExecutor(prepareId, this._workflowState, questionExecutor.PrepareResponseAsync, emitResult: false), parentId, message => !QuestionExecutor.IsComplete(message));
string inputId = QuestionExecutor.Steps.Input(actionId);
InputPort inputPort = InputPort.Create<InputRequest, InputResponse>(inputId);
@@ -234,8 +234,8 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
string captureId = QuestionExecutor.Steps.Capture(actionId);
this.ContinueWith(new DelegateActionExecutor<InputResponse>(captureId, this._workflowState, questionExecutor.CaptureResponseAsync, emitResult: false), parentId);
this.ContinueWith(new DelegateActionExecutor(postId, this._workflowState, questionExecutor.CompleteAsync), parentId, message => questionExecutor.IsComplete(message));
this._workflowModel.AddLink(captureId, prepareId, message => !questionExecutor.IsComplete(message));
this.ContinueWith(new DelegateActionExecutor(postId, this._workflowState, questionExecutor.CompleteAsync), parentId, QuestionExecutor.IsComplete);
this._workflowModel.AddLink(captureId, prepareId, message => !QuestionExecutor.IsComplete(message));
}
protected override void Visit(CreateConversation item)
@@ -29,7 +29,7 @@ internal sealed class QuestionExecutor(Question model, WorkflowFormulaState stat
protected override bool IsDiscreteAction => false;
protected override bool EmitResultEvent => false;
public bool IsComplete(object? message)
public static bool IsComplete(object? message)
{
ExecutorResultMessage executorMessage = ExecutorResultMessage.ThrowIfNot(message);
return executorMessage.Result is null;
@@ -59,7 +59,7 @@ public sealed class FileSystemJsonCheckpointStore : JsonCheckpointStore, IDispos
using StreamReader reader = new(this._indexFile, encoding: Encoding.UTF8, detectEncodingFromByteOrderMarks: false, bufferSize: -1, leaveOpen: true);
while (reader.ReadLine() is string line)
{
if (JsonSerializer.Deserialize(line, this.KeyTypeInfo) is { } info)
if (JsonSerializer.Deserialize(line, KeyTypeInfo) is { } info)
{
this.CheckpointIndex.Add(info);
}
@@ -117,7 +117,7 @@ public sealed class FileSystemJsonCheckpointStore : JsonCheckpointStore, IDispos
using Utf8JsonWriter jsonWriter = new(checkpointStream, new JsonWriterOptions() { Indented = false });
value.WriteTo(jsonWriter);
JsonSerializer.Serialize(this._indexFile!, key, this.KeyTypeInfo);
JsonSerializer.Serialize(this._indexFile!, key, KeyTypeInfo);
byte[] bytes = Encoding.UTF8.GetBytes(Environment.NewLine);
await this._indexFile!.WriteAsync(bytes, 0, bytes.Length, CancellationToken.None).ConfigureAwait(false);
@@ -8,6 +8,4 @@ namespace Microsoft.Agents.Workflows.Checkpointing;
/// <param name="RequestType"></param>
/// <param name="ResponseType"></param>
/// <param name="PortId"></param>
public record class InputPortInfo(TypeId RequestType, TypeId ResponseType, string PortId)
{
}
public record class InputPortInfo(TypeId RequestType, TypeId ResponseType, string PortId);
@@ -15,7 +15,7 @@ public abstract class JsonCheckpointStore : ICheckpointStore<JsonElement>
/// <summary>
/// A default TypeInfo for serializing the <see cref="CheckpointInfo"/> type, if needed.
/// </summary>
protected JsonTypeInfo<CheckpointInfo> KeyTypeInfo => WorkflowsJsonUtilities.JsonContext.Default.CheckpointInfo;
protected static JsonTypeInfo<CheckpointInfo> KeyTypeInfo => WorkflowsJsonUtilities.JsonContext.Default.CheckpointInfo;
/// <inheritdoc/>
public abstract ValueTask<CheckpointInfo> CreateCheckpointAsync(string runId, JsonElement value, CheckpointInfo? parent = null);
@@ -21,12 +21,9 @@ internal abstract class JsonConverterDictionarySupportBase<T> : JsonConverterBas
public override T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
SequencePosition position = reader.Position;
string? propertyName = reader.GetString();
if (propertyName is null)
{
string? propertyName = reader.GetString() ??
throw new JsonException($"Got null trying to read property name at position {position}");
}
return this.Parse(propertyName);
}
@@ -11,17 +11,23 @@ namespace Microsoft.Agents.Workflows.Checkpointing;
/// <summary>
/// Provides support for using <see cref="ScopeKey"/> values as dictionary keys when serializing and deserializing JSON.
/// </summary>
internal sealed class ScopeKeyConverter : JsonConverterDictionarySupportBase<ScopeKey>
internal sealed partial class ScopeKeyConverter : JsonConverterDictionarySupportBase<ScopeKey>
{
protected override JsonTypeInfo<ScopeKey> TypeInfo => WorkflowsJsonUtilities.JsonContext.Default.ScopeKey;
public static readonly Regex ScopeKeyPropertyNamePattern =
new(@"^(?<executorId>(((\|\|)|([^\|]))*))\|(?<scopeName>(@(((\|\|)|([^\|]))*))?)\|(?<key>(((\|\|)|([^\|]))*)?)$",
RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
private const string ScopeKeyPropertyNamePattern = @"^(?<executorId>(((\|\|)|([^\|]))*))\|(?<scopeName>(@(((\|\|)|([^\|]))*))?)\|(?<key>(((\|\|)|([^\|]))*)?)$";
#if NET
[GeneratedRegex(ScopeKeyPropertyNamePattern, RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture)]
public static partial Regex ScopeKeyPropertyNameRegex();
#else
public static Regex ScopeKeyPropertyNameRegex() => s_scopeKeyPropertyNameRegex;
private static readonly Regex s_scopeKeyPropertyNameRegex =
new(ScopeKeyPropertyNamePattern, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
#endif
protected override ScopeKey Parse(string propertyName)
{
Match scopeKeyPatternMatch = ScopeKeyPropertyNamePattern.Match(propertyName);
Match scopeKeyPatternMatch = ScopeKeyPropertyNameRegex().Match(propertyName);
if (!scopeKeyPatternMatch.Success)
{
throw new JsonException($"Invalid ScopeKey property name format. Got '{propertyName}'.");
@@ -37,7 +43,7 @@ internal sealed class ScopeKeyConverter : JsonConverterDictionarySupportBase<Sco
}
[return: NotNull]
private static string Escape(string? value, bool allowNullAndPad = false, [CallerArgumentExpression("value")] string componentName = "ScopeKey")
private static string Escape(string? value, bool allowNullAndPad = false, [CallerArgumentExpression(nameof(value))] string componentName = "ScopeKey")
{
if (!allowNullAndPad && value is null)
{
@@ -57,7 +63,7 @@ internal sealed class ScopeKeyConverter : JsonConverterDictionarySupportBase<Sco
return $"{value.Replace("|", "||")}";
}
private static string? Unescape([DisallowNull] string value, bool allowNullAndPad = false, [CallerArgumentExpression("value")] string componentName = "ScopeKey")
private static string? Unescape([DisallowNull] string value, bool allowNullAndPad = false, [CallerArgumentExpression(nameof(value))] string componentName = "ScopeKey")
{
if (value.Length == 0)
{
@@ -20,7 +20,7 @@ namespace Microsoft.Agents.Workflows;
/// <see cref="ExecutorIsh.Type.Unbound"/>.</remarks>
public class WorkflowBuilder
{
private record struct EdgeConnection(string SourceId, string TargetId)
private readonly record struct EdgeConnection(string SourceId, string TargetId)
{
public override string ToString() => $"{this.SourceId} -> {this.TargetId}";
}
@@ -221,7 +221,7 @@ public class WorkflowBuilder
return null;
}
return (object? maybeObj, int count) =>
return (maybeObj, count) =>
{
if (typeof(T) != typeof(object) && maybeObj is PortableValue portableValue)
{
@@ -93,7 +93,6 @@ public sealed class A2AHostAgent
/// </summary>
/// <param name="agentUrl">Current URL for the agent</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to cancel the operation</param>
#pragma warning disable CA1054 // URI-like parameters should not be strings
public Task<AgentCard> GetAgentCardAsync(string agentUrl, CancellationToken cancellationToken)
{
// Ensure the URL is in the correct format
@@ -103,7 +102,6 @@ public sealed class A2AHostAgent
this._agentCard.Url = agentUrl;
return Task.FromResult(this._agentCard);
}
#pragma warning restore CA1054 // URI-like parameters should not be strings
#region private
private readonly AgentCard _agentCard;
@@ -209,9 +209,7 @@ public class AgentRunResponse
structuredOutput = this.GetResultCore<T>(serializerOptions, out var failureReason);
return failureReason is null;
}
#pragma warning disable CA1031 // Do not catch general exception types
catch
#pragma warning restore CA1031
{
structuredOutput = default;
return false;
@@ -46,9 +46,7 @@ public static class AssistantExtensions
throw new ArgumentNullException(nameof(assistantClient));
}
#pragma warning disable CA2000 // Dispose objects before losing scope
var chatClient = assistantClient.AsIChatClient(assistantMetadata.Id);
#pragma warning restore CA2000 // Dispose objects before losing scope
return new ChatClientAgent(chatClient, options: new()
{
@@ -314,7 +314,6 @@ internal sealed class InProcessActorContext : IActorRuntimeContext, IAsyncDispos
Log.ActorContextDisposing(this._logger, this.ActorId.ToString());
this._cts.Dispose();
#pragma warning disable CA2012 // Use ValueTasks correctly
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
if (this._actorInstance is IDisposable actorInstanceDisposable)
{
@@ -322,12 +321,11 @@ internal sealed class InProcessActorContext : IActorRuntimeContext, IAsyncDispos
}
else
{
this._actorInstance.DisposeAsync().GetAwaiter().GetResult();
this._actorInstance.DisposeAsync().AsTask().GetAwaiter().GetResult();
}
this._actorRunTask?.GetAwaiter().GetResult();
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
#pragma warning restore CA2012 // Use ValueTasks correctly
#pragma warning restore VSTHRD002
Log.ActorContextDisposed(this._logger, this.ActorId.ToString());
}
@@ -378,7 +376,6 @@ internal sealed class InProcessActorContext : IActorRuntimeContext, IAsyncDispos
public override async ValueTask<ActorResponse> GetResponseAsync(CancellationToken cancellationToken)
{
ActorResponse response;
#pragma warning disable CA1031 // Do not catch general exception types
try
{
var responseMessage = await entry.Response
@@ -404,7 +401,6 @@ internal sealed class InProcessActorContext : IActorRuntimeContext, IAsyncDispos
Status = RequestStatus.Failed,
};
}
#pragma warning restore CA1031 // Do not catch general exception types
return response;
}
@@ -414,8 +410,8 @@ internal sealed class InProcessActorContext : IActorRuntimeContext, IAsyncDispos
if (entry.Response.Status is TaskStatus.RanToCompletion)
{
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
var responseMessage = entry.Response.GetAwaiter().GetResult();
#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits
var responseMessage = entry.Response.Result;
#pragma warning restore VSTHRD002
response = new ActorResponse
{
ActorId = context.ActorId,
@@ -477,9 +477,7 @@ public sealed class ChatClientAgent : AIAgent
{
// We were passed a thread that is service managed, but we got no conversation id back from the chat client,
// meaning the service doesn't support service managed threads, so the thread cannot be used with this service.
#pragma warning disable S2302 // "nameof" should be used - False positive.
throw new InvalidOperationException("Service did not return a valid conversation id when using a service managed thread.");
#pragma warning restore S2302 // "nameof" should be used
}
if (!string.IsNullOrWhiteSpace(responseConversationId))
-10
View File
@@ -864,9 +864,7 @@ internal static partial class Throw
public static double IfLessThan(double argument, double min, [CallerArgumentExpression(nameof(argument))] string paramName = "")
{
// strange conditional needed in order to handle NaN values correctly
#pragma warning disable S1940 // Boolean checks should not be inverted
if (!(argument >= min))
#pragma warning restore S1940 // Boolean checks should not be inverted
{
ArgumentOutOfRangeException(paramName, argument, $"Argument less than minimum value {min}");
}
@@ -885,9 +883,7 @@ internal static partial class Throw
public static double IfGreaterThan(double argument, double max, [CallerArgumentExpression(nameof(argument))] string paramName = "")
{
// strange conditional needed in order to handle NaN values correctly
#pragma warning disable S1940 // Boolean checks should not be inverted
if (!(argument <= max))
#pragma warning restore S1940 // Boolean checks should not be inverted
{
ArgumentOutOfRangeException(paramName, argument, $"Argument greater than maximum value {max}");
}
@@ -906,9 +902,7 @@ internal static partial class Throw
public static double IfLessThanOrEqual(double argument, double min, [CallerArgumentExpression(nameof(argument))] string paramName = "")
{
// strange conditional needed in order to handle NaN values correctly
#pragma warning disable S1940 // Boolean checks should not be inverted
if (!(argument > min))
#pragma warning restore S1940 // Boolean checks should not be inverted
{
ArgumentOutOfRangeException(paramName, argument, $"Argument less or equal than minimum value {min}");
}
@@ -927,9 +921,7 @@ internal static partial class Throw
public static double IfGreaterThanOrEqual(double argument, double max, [CallerArgumentExpression(nameof(argument))] string paramName = "")
{
// strange conditional needed in order to handle NaN values correctly
#pragma warning disable S1940 // Boolean checks should not be inverted
if (!(argument < max))
#pragma warning restore S1940 // Boolean checks should not be inverted
{
ArgumentOutOfRangeException(paramName, argument, $"Argument greater or equal than maximum value {max}");
}
@@ -966,9 +958,7 @@ internal static partial class Throw
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double IfZero(double argument, [CallerArgumentExpression(nameof(argument))] string paramName = "")
{
#pragma warning disable S1244 // Floating point numbers should not be tested for equality
if (argument == 0.0)
#pragma warning restore S1244 // Floating point numbers should not be tested for equality
{
ArgumentOutOfRangeException(paramName, "Argument is zero");
}
@@ -13,9 +13,7 @@ namespace AgentConformance.IntegrationTests;
public abstract class AgentTests<TAgentFixture>(Func<TAgentFixture> createAgentFixture) : IAsyncLifetime
where TAgentFixture : IAgentFixture
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
protected TAgentFixture Fixture { get; private set; }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
protected TAgentFixture Fixture { get; private set; } = default!;
public Task InitializeAsync()
{
@@ -17,10 +17,8 @@ public class AzureAIAgentsPersistentFixture : IChatClientAgentFixture
{
private static readonly AzureAIConfiguration s_config = TestConfiguration.LoadSection<AzureAIConfiguration>();
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private ChatClientAgent _agent;
private PersistentAgentsClient _persistentAgentsClient;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private ChatClientAgent _agent = null!;
private PersistentAgentsClient _persistentAgentsClient = null!;
public IChatClient ChatClient => this._agent.ChatClient;
@@ -18,9 +18,6 @@ namespace CopilotStudio.IntegrationTests;
public class CopilotStudioFixture : IAgentFixture
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public AIAgent Agent { get; private set; } = null!;
public Task<List<ChatMessage>> GetChatHistoryAsync(AgentThread thread) =>
@@ -194,9 +194,7 @@ public class CosmosActorStateStorageConcurrencyTests
};
// Act & Assert - Test null eTag (should create new document)
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
var resultWithNullETag = await storage.WriteStateAsync(testActorId, operations, null, cancellationToken);
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
var resultWithNullETag = await storage.WriteStateAsync(testActorId, operations, null!, cancellationToken);
Assert.True(resultWithNullETag.Success);
Assert.NotNull(resultWithNullETag.ETag);
Assert.NotEmpty(resultWithNullETag.ETag);
@@ -285,7 +285,6 @@ public class CosmosActorStateStorageTests
var testActorId = new ActorId("TestActor", Guid.NewGuid().ToString());
// Create a complex object with various types
#pragma warning disable CA1861 // Avoid constant arrays as arguments
var complexObject = new
{
Id = 123,
@@ -295,7 +294,7 @@ public class CosmosActorStateStorageTests
{ "StringProp", "value" },
{ "NumberProp", 42.5 },
{ "BoolProp", true },
{ "ArrayProp", new[] { 1, 2, 3 } },
{ "ArrayProp", (int[])[1, 2, 3] },
{ "NestedProp", new { Inner = "nested value" } }
},
Tags = new[] { "tag1", "tag2", "tag3" },
@@ -305,7 +304,6 @@ public class CosmosActorStateStorageTests
{ "author", "test" }
}
};
#pragma warning restore CA1861 // Avoid constant arrays as arguments
const string Key = "complexObject";
var value = JsonSerializer.SerializeToElement(complexObject);
@@ -20,7 +20,7 @@ namespace Microsoft.Agents.Workflows.Declarative.IntegrationTests;
/// Tests execution of workflow created by <see cref="DeclarativeWorkflowBuilder"/>.
/// </summary>
[Collection("Global")]
public sealed class DeclarativeWorkflowTest(ITestOutputHelper output, AgentFixture agentFixture) : WorkflowTest(output), IClassFixture<AgentFixture>
public sealed class DeclarativeWorkflowTest(ITestOutputHelper output) : WorkflowTest(output)
{
[Theory]
[InlineData("SendActivity.yaml", "SendActivity.json")]
@@ -58,7 +58,7 @@ public sealed class DeclarativeWorkflowTest(ITestOutputHelper output, AgentFixtu
AzureAIConfiguration? foundryConfig = configuration.GetSection("AzureAI").Get<AzureAIConfiguration>();
Assert.NotNull(foundryConfig);
IReadOnlyDictionary<string, string?> agentMap = await agentFixture.GetAgentsAsync(foundryConfig);
IReadOnlyDictionary<string, string?> agentMap = await AgentFixture.GetAgentsAsync(foundryConfig);
IConfiguration workflowConfig =
new ConfigurationBuilder()
@@ -12,7 +12,7 @@ public sealed class AgentFixture : IDisposable
{
private static IReadOnlyDictionary<string, string?>? s_agentMap;
internal async Task<IReadOnlyDictionary<string, string?>> GetAgentsAsync(AzureAIConfiguration config, CancellationToken cancellationToken = default)
internal static async Task<IReadOnlyDictionary<string, string?>> GetAgentsAsync(AzureAIConfiguration config, CancellationToken cancellationToken = default)
{
s_agentMap ??= await AgentFactory.CreateAsync("Agents", config, cancellationToken);
@@ -495,8 +495,8 @@ public class WorkflowExpressionEngineTests : RecalcEngineTest
=> this.EvaluateExpression((evaluator) => evaluator.GetValue(expression), expectedValue, expectedSensitivity);
private void EvaluateInvalidExpression<TValue, TException>(ObjectExpression<TValue> expression)
where TException : Exception
where TValue : BotElement
where TException : Exception
=> this.EvaluateInvalidExpression<TException>((evaluator) => evaluator.GetValue(expression));
private ImmutableArray<TValue> EvaluateExpression<TValue>(ArrayExpression<TValue> expression, TValue[] expectedValue)
@@ -70,7 +70,7 @@ public class JsonSerializationTests
{
return deserialized => deserialized.AssemblyName == type.AssemblyName &&
deserialized.TypeName == type.TypeName &&
deserialized.IsMatch(typeof(Type));
deserialized.IsMatch<Type>();
}
}
@@ -84,7 +84,7 @@ public class JsonSerializationTests
{
return deserialized => deserialized.ExecutorId == executorInfo.ExecutorId &&
// Rely on the TypeId test to probe TypeId serialization - just validate that we got a functional TypeId
deserialized.ExecutorType.IsMatch(typeof(ForwardMessageExecutor<string>));
deserialized.ExecutorType.IsMatch<ForwardMessageExecutor<string>>();
}
}
@@ -169,7 +169,7 @@ public class JsonSerializationTests
return builder.BuildWithOutput<string, int, int>(
intToString,
StreamingAggregators.Last<int>(), (int _, int __) => true);
StreamingAggregators.Last<int>(), (_, __) => true);
}
private static WorkflowInfo TestWorkflowInfo => CreateTestWorkflow().ToWorkflowInfo();
@@ -232,7 +232,7 @@ public class JsonSerializationTests
JsonMarshaller marshaller = new();
JsonElement jsonElement = marshaller.Marshal(prototype, typeof(WorkflowInfo));
JsonElement jsonElement = marshaller.Marshal(prototype);
WorkflowInfo deserialized = marshaller.Marshal<WorkflowInfo>(jsonElement);
ValidateWorkflowInfo(deserialized, prototype);
@@ -21,8 +21,8 @@ internal static class Step2EntryPoint
RemoveSpamExecutor removeSpam = new();
return new WorkflowBuilder(detectSpam)
.AddEdge(detectSpam, respondToMessage, (bool isSpam) => isSpam is false) // If not spam, respond
.AddEdge(detectSpam, removeSpam, (bool isSpam) => isSpam is true) // If spam, remove
.AddEdge(detectSpam, respondToMessage, (bool isSpam) => !isSpam) // If not spam, respond
.AddEdge(detectSpam, removeSpam, (bool isSpam) => isSpam) // If spam, remove
.Build<string>();
}
}
@@ -104,30 +104,12 @@ internal sealed class JudgeExecutor : ReflectingExecutor<JudgeExecutor>, IMessag
public async ValueTask<NumberSignal> HandleAsync(int message, IWorkflowContext context)
{
if (!this.Tries.HasValue)
{
this.Tries = 1;
}
else
{
this.Tries++;
}
this.Tries = this.Tries is int tries ? tries + 1 : 1;
NumberSignal result;
if (message == this._targetNumber)
{
result = NumberSignal.Matched;
}
else if (message < this._targetNumber)
{
result = NumberSignal.Below;
}
else
{
result = NumberSignal.Above;
}
return result;
return
message == this._targetNumber ? NumberSignal.Matched :
message < this._targetNumber ? NumberSignal.Below :
NumberSignal.Above;
}
protected internal override ValueTask OnCheckpointingAsync(IWorkflowContext context, CancellationToken cancellation = default)
@@ -16,7 +16,7 @@ internal static class Step4EntryPoint
return new WorkflowBuilder(guessNumber)
.AddEdge(guessNumber, judge)
.AddEdge(judge, guessNumber, (NumberSignal signal) => signal != NumberSignal.Matched)
.BuildWithOutput<NumberSignal, NumberSignal, string>(judge, ComputeStreamingOutput, (NumberSignal s, string? _) => s == NumberSignal.Matched);
.BuildWithOutput<NumberSignal, NumberSignal, string>(judge, ComputeStreamingOutput, (s, _) => s is NumberSignal.Matched);
}
public static Workflow<NumberSignal, string> WorkflowInstance
@@ -43,7 +43,7 @@ public class SampleSmokeTest
Assert.Collection(lines,
line => Assert.Contains($"UppercaseExecutor: {INPUT.ToUpperInvariant()}", line),
line => Assert.Contains($"ReverseTextExecutor: {new string(INPUT.ToUpperInvariant().Reverse().ToArray())}", line)
line => Assert.Contains($"ReverseTextExecutor: {string.Concat(INPUT.ToUpperInvariant().Reverse())}", line)
);
}
@@ -396,7 +396,7 @@ public sealed class A2AAgentTests : IDisposable
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Capture the request content
#pragma warning disable CA2016 // Forward the 'CancellationToken' parameter to methods; overload doesn't exist on .NET …
#pragma warning disable CA2016 // Forward the 'CancellationToken' parameter to methods; overload doesn't exist downlevel
var content = await request.Content!.ReadAsStringAsync();
#pragma warning restore CA2016
@@ -272,13 +272,15 @@ public class AgentThreadTests
{
// Arrange
Mock<AIContextProvider> mockProvider = new();
var providerStateElement = JsonSerializer.SerializeToElement(new[] { "CP1" }, TestJsonSerializerContext.Default.StringArray);
var providerStateElement = JsonSerializer.SerializeToElement(["CP1"], TestJsonSerializerContext.Default.StringArray);
mockProvider
.Setup(m => m.SerializeAsync(It.IsAny<JsonSerializerOptions?>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(providerStateElement);
var thread = new AgentThread();
thread.AIContextProvider = mockProvider.Object;
var thread = new AgentThread
{
AIContextProvider = mockProvider.Object
};
// Act
var json = await thread.SerializeAsync();
@@ -236,7 +236,7 @@ public class AgentProxyTests
// Act & Assert
await Assert.ThrowsAsync<ArgumentException>(async () =>
{
await foreach (var _ in proxy.RunStreamingAsync(Array.Empty<ChatMessage>(), invalidThread, cancellationToken: CancellationToken.None))
await foreach (var _ in proxy.RunStreamingAsync([], invalidThread, cancellationToken: CancellationToken.None))
{
}
});
@@ -255,7 +255,7 @@ public class AgentProxyTests
var proxyThread = new AgentProxyThread();
// Act & Assert
await foreach (var _ in proxy.RunStreamingAsync(Array.Empty<ChatMessage>(), proxyThread, cancellationToken: CancellationToken.None))
await foreach (var _ in proxy.RunStreamingAsync([], proxyThread, cancellationToken: CancellationToken.None))
{
// No items expected
}
@@ -249,7 +249,7 @@ public class AgentProxyThreadTests
var thread = new AgentProxyThread();
// Assert
Assert.IsAssignableFrom<AgentThread>(thread);
Assert.IsType<AgentThread>(thread, exactMatch: false);
}
/// <summary>
@@ -478,9 +478,7 @@ public class JsonSerializationTests
Assert.Equal(253, dataInResult.Length);
// Verify that the truncated data matches the first 250 characters of the original
#pragma warning disable CA1846 // Prefer 'AsSpan' over 'Substring'
Assert.Equal(rawText.Substring(0, 250), dataInResult.Substring(0, 250));
#pragma warning restore CA1846
}
[Fact]
@@ -1470,10 +1470,12 @@ public class OpenTelemetryAgentTests
static async IAsyncEnumerable<AgentRunResponseUpdate> ThrowingAsyncEnumerableAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
{
await Task.Yield();
throw new InvalidOperationException("Streaming error");
#pragma warning disable CS0162 // Unreachable code detected
if (Environment.ProcessorCount > 0) // always true
{
throw new InvalidOperationException("Streaming error");
}
yield break;
#pragma warning restore CS0162
}
static async IAsyncEnumerable<AgentRunResponseUpdate> CreateStreamingResponseAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
@@ -16,10 +16,8 @@ public class OpenAIAssistantFixture : IChatClientAgentFixture
{
private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection<OpenAIConfiguration>();
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private AssistantClient? _assistantClient;
private ChatClientAgent _agent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private ChatClientAgent _agent = null!;
public AIAgent Agent => this._agent;
@@ -17,14 +17,12 @@ public class OpenAIChatCompletionFixture : IChatClientAgentFixture
private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection<OpenAIConfiguration>();
private readonly bool _useReasoningModel;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private ChatClientAgent _agent;
private ChatClientAgent _agent = null!;
public OpenAIChatCompletionFixture(bool useReasoningChatModel)
{
this._useReasoningModel = useReasoningChatModel;
}
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
public AIAgent Agent => this._agent;
@@ -18,10 +18,8 @@ public class OpenAIResponseFixture(bool store) : IChatClientAgentFixture
{
private static readonly OpenAIConfiguration s_config = TestConfiguration.LoadSection<OpenAIConfiguration>();
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private OpenAIResponseClient _openAIResponseClient;
private ChatClientAgent _agent;
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
private OpenAIResponseClient _openAIResponseClient = null!;
private ChatClientAgent _agent = null!;
public AIAgent Agent => this._agent;