Added FxCop tp Dialogs.Adaptive (#4285)

Added CultureInfo and StringComparison parameters to several string operations.
Added some using statements for disposable objects.
Added project wide exclude for CA2225 (Operator overloads have named alternates) in Dialogs.Adaptive we should address this if we want to support other platforms than C# see https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2225?view=vs-2019.
Added several #pragme exlcudes to collection properties that shouln't have a setter.
Added several other #pragma disable for other rules for code that can't be changed because of binary compat.
Replaced several Count() calls by the Count property.
Added solution wide exclude for CA1308 Normalize strings to uppercase and removed specific excludes from projects and code (we mostly use lowercase in our project and the rule doesn't apply).
This commit is contained in:
Gabo Gilabert 2020-07-17 13:46:41 -04:00 коммит произвёл GitHub
Родитель 7a6d061352
Коммит 614697f884
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
58 изменённых файлов: 222 добавлений и 117 удалений

Просмотреть файл

@ -9,6 +9,7 @@
<Rules AnalyzerId="Microsoft.CodeQuality.Analyzers" RuleNamespace="Microsoft.CodeQuality.Analyzers">
<Rule Id="CA1054" Action="None" /> <!-- UriParametersShouldNotBeStrings -->
<Rule Id="CA1062" Action="None" /> <!-- ValidateArgumentsOfPublicMethods -->
<Rule Id="CA1308" Action="None" /> <!-- Normalize strings to uppercase (most of our operations are normalized on lowercase -->
<Rule Id="CA1822" Action="None" /> <!-- Ignore Mark members as static -->
</Rules>
<Rules AnalyzerId="Microsoft.NetCore.Analyzers" RuleNamespace="Microsoft.NetCore.Analyzers">

Просмотреть файл

@ -65,9 +65,7 @@ namespace Microsoft.Bot.Builder.Adapters.Facebook
using (var request = new HttpRequestMessage())
{
#pragma warning disable CA1308 // the appsecret_proof should be sent in lowerCase.
request.RequestUri = new Uri($"https://{_options.FacebookApiHost}/{_options.FacebookApiVersion + path}?access_token={_options.FacebookAccessToken}&appsecret_proof={proof.ToLowerInvariant()}");
#pragma warning restore CA1308 // the appsecret_proof should be sent in lowerCase.
request.Method = method;
var json = JsonConvert.SerializeObject(
payload,

Просмотреть файл

@ -21,9 +21,7 @@
<!-- SX1309: FieldNamesShouldBeginWithUnderscores should be fixed as part of https://github.com/microsoft/botframework-sdk/issues/5933 -->
<!-- CA2225: Operator overloads have named alternates, excluding for now, we should address this if we want to support other platforms than C#
see https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2225?view=vs-2019 .-->
<!-- CA1308: Normalize strings to uppercase. AdaptiveExpressions assumes all strings are normalized to lowercase
(see for details on this https://docs.microsoft.com/en-us/visualstudio/code-quality/ca1308?view=vs-2019 rule) -->
<NoWarn>$(NoWarn);CS1591;SX1309;CA2225;CA1308</NoWarn>
<NoWarn>$(NoWarn);CS1591;SX1309;CA2225</NoWarn>
</PropertyGroup>
<PropertyGroup>

Просмотреть файл

@ -39,9 +39,7 @@ namespace Microsoft.Bot.Builder.AI.Luis
}
var di = new DirectoryInfo(botRoot);
#pragma warning disable CA1308 // Normalize strings to uppercase (file names are normalized as lowercase, ignoring)
foreach (var file in di.GetFiles($"luis.settings.{environment.ToLowerInvariant()}.{luisRegion}.json", SearchOption.AllDirectories))
#pragma warning restore CA1308 // Normalize strings to uppercase
{
var relative = file.FullName.Substring(di.FullName.Length);
if (!relative.Contains("bin\\") && !relative.Contains("obj\\"))

Просмотреть файл

@ -14,10 +14,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
public ActionChangeType ChangeType { get; set; } = ActionChangeType.InsertActions;
[JsonProperty(PropertyName = "actions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<ActionState> Actions { get; set; } = new List<ActionState>();
#pragma warning restore CA2227 // Collection properties should be read only
[JsonProperty(PropertyName = "tags")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<string> Tags { get; set; } = new List<string>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets turn state associated with the plan change list (it will be applied to turn state when plan is applied).
@ -26,6 +30,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// Turn state associated with the plan change list (it will be applied to turn state when plan is applied).
/// </value>
[JsonProperty(PropertyName = "turn")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public Dictionary<string, object> Turn { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
}
}

Просмотреть файл

@ -38,7 +38,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// <value>
/// List of actions being executed.
/// </value>
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<ActionState> Actions { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets list of changes that are queued to be applied.

Просмотреть файл

@ -32,7 +32,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Gets or sets the actions to execute.
/// </summary>
/// <value>The actions to execute.</value>
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> Actions { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default)
{
@ -190,7 +192,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
// get the action for the offset
dc.State.SetValue(OFFSETKEY, offset);
if (this.Actions == null || this.Actions.Count() <= offset)
if (this.Actions == null || this.Actions.Count <= offset)
{
return await dc.EndDialogAsync(null, cancellationToken).ConfigureAwait(false);
}

Просмотреть файл

@ -3,7 +3,9 @@
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
{
#pragma warning disable CA1052 // Static holder types should be Static or NotInheritable (we can't change this without breaking binary compat)
public class ActionScopeCommands
#pragma warning restore CA1052 // Static holder types should be Static or NotInheritable
{
/// <summary>
/// Change execution order to the action by id.

Просмотреть файл

@ -7,7 +7,9 @@ using Newtonsoft.Json;
namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
{
#pragma warning disable CA1716 // Identifiers should not match keywords (by design and we can't change this without breaking binary compat)
public class Case : ActionScope
#pragma warning restore CA1716 // Identifiers should not match keywords
{
public Case(string value = null, IEnumerable<Dialog> actions = null)
: base(actions)

Просмотреть файл

@ -80,9 +80,11 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
Debug.WriteLine($"{path}: {actionsIds.Count()} actions remaining.");
}
#pragma warning disable CA1031 // Do not catch general exception types (we catch any exception and we write it to the debugger).
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine($"Failed to collect full debug dump. Error: {ex.ToString()}");
Debug.WriteLine($"Failed to collect full debug dump. Error: {ex}");
}
}
}

Просмотреть файл

@ -49,7 +49,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Collection of property paths to remove.
/// </value>
[JsonProperty("properties")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<StringExpression> Properties { get; set; } = new List<StringExpression>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{

Просмотреть файл

@ -31,7 +31,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// options if there is no explicit options set.
/// </value>
[JsonExtensionData(ReadData = true, WriteData = true)]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
protected Dictionary<string, object> Properties { get; set; } = new Dictionary<string, object>();
#pragma warning restore CA2227 // Collection properties should be read only
protected override object BindOptions(DialogContext dc, object options)
{

Просмотреть файл

@ -51,7 +51,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// The actions to be applied to the active action.
/// </value>
[JsonProperty("actions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> Actions { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets the type of change to appy to the active actions.

Просмотреть файл

@ -205,7 +205,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
if (error == null && itemResult != null)
{
result = false;
for (var i = 0; i < array.Count(); ++i)
for (var i = 0; i < array.Count; ++i)
{
if (array[i].ToString() == itemResult.ToString() || JToken.DeepEquals(array[i], JToken.FromObject(itemResult)))
{

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
@ -21,9 +22,6 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
[JsonProperty("$kind")]
public const string Kind = "Microsoft.ForeachPage";
private const string FOREACHPAGE = "dialog.foreach.page";
private const string FOREACHPAGEINDEX = "dialog.foreach.pageindex";
[JsonConstructor]
public ForeachPage([CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
: base()
@ -132,9 +130,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
{
for (int i = index; i < end; i++)
{
if (((JObject)list).SelectToken(i.ToString()).HasValues)
if (((JObject)list).SelectToken(i.ToString(CultureInfo.InvariantCulture)).HasValues)
{
page.Add(((JObject)list).SelectToken(i.ToString()));
page.Add(((JObject)list).SelectToken(i.ToString(CultureInfo.InvariantCulture)));
}
}
}

Просмотреть файл

@ -58,7 +58,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
var actionScopeResult = new ActionScopeResult()
{
ActionScopeCommand = ActionScopeCommands.GotoAction,
ActionId = this.ActionId?.GetValue(dc.State) ?? throw new ArgumentNullException(nameof(ActionId))
ActionId = this.ActionId?.GetValue(dc.State) ?? throw new InvalidOperationException($"Unable to get a {nameof(ActionId)} from state.")
};
return await dc.EndDialogAsync(result: actionScopeResult, cancellationToken: cancellationToken).ConfigureAwait(false);

Просмотреть файл

@ -46,7 +46,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
this.RegisterSourceLocation(callerPath, callerLine);
}
#pragma warning disable CA1717 // Only FlagsAttribute enums should have plural names (we can't change this without breaking binary compat).
public enum ResponseTypes
#pragma warning restore CA1717 // Only FlagsAttribute enums should have plural names
{
/// <summary>
/// No response expected
@ -150,7 +152,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Headers.
/// </value>
[JsonProperty("headers")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public Dictionary<string, StringExpression> Headers { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets body payload.
@ -196,7 +200,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
return await dc.EndDialogAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
}
#pragma warning disable CA2000 // Dispose objects before losing scope (excluding for now, to fix this we would need to understand better how HttpClient gets into turn state and determine if we should dispose it or not, this should also be analyzed once we start using HttpClientFactory).
var client = dc.Context.TurnState.Get<HttpClient>() ?? new HttpClient();
#pragma warning restore CA2000 // Dispose objects before losing scope
// Single command running with a copy of the original data
client.DefaultRequestHeaders.Clear();
@ -254,10 +260,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
}
else
{
var postContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(postContent?.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.PostAsync(instanceUrl, postContent, cancellationToken).ConfigureAwait(false);
using (var postContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType))
{
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(postContent?.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.PostAsync(instanceUrl, postContent, cancellationToken).ConfigureAwait(false);
}
}
break;
@ -265,16 +273,20 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
case HttpMethod.PATCH:
if (instanceBody == null)
{
var request = new HttpRequestMessage(new System.Net.Http.HttpMethod("PATCH"), instanceUrl);
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
using (var request = new HttpRequestMessage(new System.Net.Http.HttpMethod("PATCH"), instanceUrl))
{
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
else
{
var request = new HttpRequestMessage(new System.Net.Http.HttpMethod("PATCH"), instanceUrl);
request.Content = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
using (var request = new HttpRequestMessage(new System.Net.Http.HttpMethod("PATCH"), instanceUrl))
{
request.Content = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(request.Content.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false);
}
}
break;
@ -286,10 +298,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
}
else
{
var putContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType);
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(putContent.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.PutAsync(instanceUrl, putContent, cancellationToken).ConfigureAwait(false);
using (var putContent = new StringContent(instanceBody.ToString(), Encoding.UTF8, contentType))
{
traceInfo.request.content = instanceBody.ToString();
traceInfo.request.headers = JObject.FromObject(putContent.Headers.ToDictionary(t => t.Key, t => (object)t.Value?.FirstOrDefault()));
response = await client.PutAsync(instanceUrl, putContent, cancellationToken).ConfigureAwait(false);
}
}
break;
@ -303,7 +317,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
break;
}
Result requestResult = new Result(response.Headers)
var requestResult = new Result(response.Headers)
{
StatusCode = (int)response.StatusCode,
ReasonPhrase = response.ReasonPhrase,
@ -326,12 +340,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
break;
case ResponseTypes.Json:
// Try set with JOjbect for further retreiving
// Try set with JOjbect for further retrieving
try
{
content = JToken.Parse((string)content);
}
#pragma warning disable CA1031 // Do not catch general exception types (just stringify the content if we can't parse the content).
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
content = content.ToString();
}
@ -416,7 +432,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// <summary>
/// Result data of the the http operation.
/// </summary>
#pragma warning disable CA1034 // Nested types should not be visible (this should have been a separate class but we can't change it without breaking binary compat).
public class Result
#pragma warning restore CA1034 // Nested types should not be visible
{
public Result()
{

Просмотреть файл

@ -55,10 +55,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
public BoolExpression Disabled { get; set; }
[JsonProperty("actions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> Actions { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
[JsonProperty("elseActions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> ElseActions { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
protected ActionScope TrueScope
{

Просмотреть файл

@ -45,7 +45,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Additional property settings as property=value pairs.
/// </value>
[JsonProperty("assignments")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<PropertyAssignment> Assignments { get; set; } = new List<PropertyAssignment>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{

Просмотреть файл

@ -59,7 +59,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Default case.
/// </value>
[JsonProperty("default")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> Default { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets Cases.
@ -68,7 +70,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// Cases.
/// </value>
[JsonProperty("cases")]
#pragma warning disable CA2227 // Collection properties should be read only
public List<Case> Cases { get; set; } = new List<Case>();
#pragma warning restore CA2227 // Collection properties should be read only
protected ActionScope DefaultScope
{

Просмотреть файл

@ -54,7 +54,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
/// A collection of properties to attach to the tracked event.
/// </value>
[JsonProperty]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public Dictionary<string, StringExpression> Properties { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc, object options = null, CancellationToken cancellationToken = default(CancellationToken))
{

Просмотреть файл

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
@ -37,12 +38,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
private const string InstanceKey = "$instance";
private const string NoneIntentKey = "None";
private const string OperationsKey = "$operations";
private const string PROPERTYNameKey = "PROPERTYName";
private const string PropertyNameKey = "PROPERTYName";
private const string UtteranceKey = "utterance";
// unique key for language generator turn property, (TURN STATE ONLY)
private readonly string generatorTurnKey = Guid.NewGuid().ToString();
// unique key for change tracking of the turn state (TURN STATE ONLY)
private readonly string changeTurnKey = Guid.NewGuid().ToString();
@ -86,7 +84,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// Trigger handlers to respond to conditions which modifying the executing plan.
/// </value>
[JsonProperty("triggers")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public virtual List<OnCondition> Triggers { get; set; } = new List<OnCondition>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets a value indicating whether to end the dialog when there are no actions to execute.
@ -125,7 +125,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// </summary>
/// <value>JSON Schema for the dialog.</value>
[JsonProperty("schema")]
#pragma warning disable CA2227 // Collection properties should be read only
public JObject Schema
#pragma warning restore CA2227 // Collection properties should be read only
{
get => dialogSchema?.Schema;
set
@ -389,7 +391,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
actionContext.State.SetValue(DialogPath.EventCounter, ++count);
// Look for triggered evt
var handled = await QueueFirstMatchAsync(actionContext, dialogEvent, preBubble, cancellationToken).ConfigureAwait(false);
var handled = await QueueFirstMatchAsync(actionContext, dialogEvent, cancellationToken).ConfigureAwait(false);
if (handled)
{
@ -638,7 +640,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
}
#pragma warning disable CA1801 // Review unused parameters (we can't remove the cancellationToken parameter withoutt breaking binary compat).
protected Task<bool> EndCurrentActionAsync(ActionContext actionContext, CancellationToken cancellationToken = default)
#pragma warning restore CA1801 // Review unused parameters
{
if (actionContext.Actions.Any())
{
@ -661,7 +665,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
// Still processing assignments
return await ContinueActionsAsync(actionContext, null, cancellationToken).ConfigureAwait(false);
}
else if (ShouldEnd(actionContext))
else if (ShouldEnd())
{
actionContext.State.TryGetValue<object>(DefaultResultProperty, out var result);
return await actionContext.EndDialogAsync(result, cancellationToken).ConfigureAwait(false);
@ -755,7 +759,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
if (trigger.Id == null)
{
trigger.Id = id++.ToString();
trigger.Id = id++.ToString(CultureInfo.InvariantCulture);
}
}
@ -833,12 +837,12 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return dc.Stack.Count > 0 ? $"{dc.Stack.Count}:{dc.ActiveDialog.Id}" : string.Empty;
}
private async Task<bool> QueueFirstMatchAsync(ActionContext actionContext, DialogEvent dialogEvent, bool preBubble, CancellationToken cancellationToken)
private async Task<bool> QueueFirstMatchAsync(ActionContext actionContext, DialogEvent dialogEvent, CancellationToken cancellationToken)
{
var selection = await Selector.SelectAsync(actionContext, cancellationToken).ConfigureAwait(false);
if (selection.Any())
{
var condition = selection.First();
var condition = selection[0];
await actionContext.DebuggerStepAsync(condition, dialogEvent, cancellationToken).ConfigureAwait(false);
Trace.TraceInformation($"Executing Dialog: {Id} Rule[{condition.Id}]: {condition.GetType().Name}: {condition.GetExpression()}");
@ -863,7 +867,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return false;
}
private bool ShouldEnd(DialogContext dc)
private bool ShouldEnd()
{
return AutoEndDialog;
}
@ -966,13 +970,13 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
// Find PROPERTYName so we can apply it to other entities
foreach (var child in composite)
{
if (child.Name == PROPERTYNameKey)
if (child.Name == PropertyNameKey)
{
// Expand PROPERTYName and fold single match into siblings span
// TODO: Would we ever need to handle multiple?
var infos = new Dictionary<string, List<EntityInfo>>();
ExpandEntity(child, childInstance, name, null, turn, text, infos);
pname = infos[PROPERTYNameKey].First();
pname = infos[PropertyNameKey].First();
break;
}
}
@ -981,7 +985,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
foreach (var child in composite)
{
// Drop PROPERTYName if we are applying it to other entities
if (pname == null || child.Name != PROPERTYNameKey)
if (pname == null || child.Name != PropertyNameKey)
{
ExpandEntity(child, childInstance, name, pname, turn, text, entityToInfo);
}
@ -1024,10 +1028,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
return val;
});
for (var i = 0; i < infos.Count(); ++i)
for (var i = 0; i < infos.Count; ++i)
{
var current = infos[i];
for (var j = i + 1; j < infos.Count();)
for (var j = i + 1; j < infos.Count;)
{
var alt = infos[j];
if (current.Covers(alt))
@ -1105,7 +1109,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
else
{
if (op != null && name == PROPERTYNameKey)
if (op != null && name == PropertyNameKey)
{
foreach (var property in val as JArray)
{
@ -1248,7 +1252,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
else
{
result = new List<string> { PROPERTYNameKey };
result = new List<string> { PropertyNameKey };
}
}
else
@ -1328,7 +1332,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
var assignments = new EntityAssignments();
if (!actionContext.State.TryGetValue<string[]>(DialogPath.ExpectedProperties, out var expected))
{
expected = new string[0];
expected = Array.Empty<string>();
}
// default op from the last Ask action.
@ -1373,7 +1377,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
existing.Dequeue(actionContext);
lastEvent = null;
}
else if (lastEvent == AdaptiveEvents.ChooseProperty && candidate.Operation == null && candidate.Entity.Name == PROPERTYNameKey)
else if (lastEvent == AdaptiveEvents.ChooseProperty && candidate.Operation == null && candidate.Entity.Name == PropertyNameKey)
{
// NOTE: This assumes the existence of an entity named PROPERTYName for resolving this ambiguity
choices = existing.NextAssignment().Alternatives.ToList();
@ -1425,7 +1429,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
existing.Dequeue(actionContext);
}
var operations = new EntityAssignmentComparer(dialogSchema.Schema[OperationsKey]?.ToObject<string[]>() ?? new string[0]);
var operations = new EntityAssignmentComparer(dialogSchema.Schema[OperationsKey]?.ToObject<string[]>() ?? Array.Empty<string>());
MergeAssignments(assignments, existing, operations);
return usedEntities.ToList();
}
@ -1441,7 +1445,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
{
foreach (var bAlt in b.Alternatives)
{
if (aAlt.Property == bAlt.Property && aAlt.Entity.Name != PROPERTYNameKey && bAlt.Entity.Name != PROPERTYNameKey)
if (aAlt.Property == bAlt.Property && aAlt.Entity.Name != PropertyNameKey && bAlt.Entity.Name != PropertyNameKey)
{
var prop = dialogSchema.PathToSchema(aAlt.Property);
if (!prop.IsArray)

Просмотреть файл

@ -13,6 +13,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
[JsonProperty(PropertyName = "actions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<ActionState> Actions { get; set; } = new List<ActionState>();
#pragma warning restore CA2227 // Collection properties should be read only
}
}

Просмотреть файл

@ -23,7 +23,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// Gets or sets the queue of pending entity assignments.
/// </summary>
/// <value>Queue of entity assignments.</value>
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<EntityAssignment> Assignments { get; set; } = new List<EntityAssignment>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Read entity event queue from memory.

Просмотреть файл

@ -49,7 +49,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
/// <value>
/// Generators.
/// </value>
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public ConcurrentDictionary<string, LanguageGenerator> LanguageGenerators { get; set; } = new ConcurrentDictionary<string, LanguageGenerator>(StringComparer.OrdinalIgnoreCase);
#pragma warning restore CA2227 // Collection properties should be read only
public static ImportResolverDelegate ResourceExplorerResolver(string locale, Dictionary<string, IList<Resource>> resourceMapping)
{
@ -60,7 +62,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
var resourceName = Path.GetFileName(PathUtils.NormalizePath(id));
var resource = resources.FirstOrDefault(u => LGResourceLoader.ParseLGFileName(u.Id).prefix.ToLower() == LGResourceLoader.ParseLGFileName(resourceName).prefix.ToLower());
var resource = resources.FirstOrDefault(u => LGResourceLoader.ParseLGFileName(u.Id).prefix.ToLowerInvariant() == LGResourceLoader.ParseLGFileName(resourceName).prefix.ToLowerInvariant());
if (resource == null)
{
throw new Exception($"There is no matching LG resource for {resourceName}");
@ -76,7 +78,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
private void ResourceExplorer_Changed(object sender, IEnumerable<Resource> resources)
{
// reload changed LG files
foreach (var resource in resources.Where(r => Path.GetExtension(r.Id).ToLower() == ".lg"))
foreach (var resource in resources.Where(r => Path.GetExtension(r.Id).ToLowerInvariant() == ".lg"))
{
LanguageGenerators[resource.Id] = GetTemplateEngineLanguageGenerator(resource);
}

Просмотреть файл

@ -29,7 +29,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
/// The language generators for multiple languages.
/// </value>
[JsonProperty("languageGenerators")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public ConcurrentDictionary<string, LanguageGenerator> LanguageGenerators { get; set; } = new ConcurrentDictionary<string, LanguageGenerator>(StringComparer.OrdinalIgnoreCase);
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Implementation of lookup by locale. This uses internal dictionary to lookup.

Просмотреть файл

@ -23,7 +23,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
}
[JsonProperty("languagePolicy")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public LanguagePolicy LanguagePolicy { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Abstract method to get an ILanguageGenerator by locale.
@ -44,7 +46,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
/// <returns>The generator.</returns>
public override async Task<object> GenerateAsync(DialogContext dialogContext, string template, object data, CancellationToken cancellationToken = default)
{
var targetLocale = dialogContext.Context.Activity.Locale?.ToLower() ?? string.Empty;
var targetLocale = dialogContext.Context.Activity.Locale?.ToLowerInvariant() ?? string.Empty;
// priority
// 1. local policy
@ -62,7 +64,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
}
// append empty as fallback to end
if (targetLocale != string.Empty && languagePolicy.ContainsKey(string.Empty))
if (targetLocale.Length != 0 && languagePolicy.ContainsKey(string.Empty))
{
fallbackLocales.AddRange(languagePolicy[string.Empty]);
}
@ -93,7 +95,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
{
return await generator.GenerateAsync(dialogContext, template, data, cancellationToken).ConfigureAwait(false);
}
#pragma warning disable CA1031 // Do not catch general exception types (catch any exception and add it to the errors list).
catch (Exception err)
#pragma warning restore CA1031 // Do not catch general exception types
{
errors.Add(err.Message);
}

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
@ -75,7 +76,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Actions
&& !expected.Any(prop => !lastExpectedProperties.Contains(prop))
&& !lastExpectedProperties.Any(prop => !expected.Contains(prop))
&& dc.State.TryGetValue(DialogPath.LastTriggerEvent, out DialogEvent lastTrigger)
&& lastTrigger.Name.Equals(trigger.Name))
&& lastTrigger.Name.Equals(trigger.Name, StringComparison.Ordinal))
{
retries++;
}

Просмотреть файл

@ -10,6 +10,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
public class ChoiceInputOptions : InputDialogOptions
{
[JsonProperty("choices")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Choice> Choices { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
}
}

Просмотреть файл

@ -17,8 +17,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
public abstract class InputDialog : Dialog
{
#pragma warning disable SA1310 // Field should not contain underscore.
#pragma warning disable CA1707 // Identifiers should not contain underscores (we shouldn't use screaming caps, but we can't change this without breaking binary compat)
protected const string TURN_COUNT_PROPERTY = "this.turnCount";
protected const string VALUE_PROPERTY = "this.value";
#pragma warning restore CA1707 // Identifiers should not contain underscores
#pragma warning restore SA1310 // Field should not contain underscore.
/// <summary>
@ -126,7 +128,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
/// The expressions to run to validate the input.
/// </value>
[JsonProperty("validations")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<BoolExpression> Validations { get; set; } = new List<BoolExpression>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets maximum number of times to ask the user for this value before the dialog gives up.

Просмотреть файл

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Security.Claims;
@ -204,7 +205,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
// Increment attempt count
// Convert.ToInt32 For issue https://github.com/Microsoft/botbuilder-dotnet/issues/1859
promptState[AttemptCountKey] = Convert.ToInt32(promptState[AttemptCountKey]) + 1;
promptState[AttemptCountKey] = Convert.ToInt32(promptState[AttemptCountKey], CultureInfo.InvariantCulture) + 1;
// Validate the return value
var inputState = InputState.Invalid;
@ -431,7 +432,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
else if (IsTeamsVerificationInvoke(turnContext))
{
var magicCodeObject = turnContext.Activity.Value as JObject;
var magicCode = magicCodeObject.GetValue("state")?.ToString();
var magicCode = magicCodeObject.GetValue("state", StringComparison.Ordinal)?.ToString();
if (!(turnContext.Adapter is IExtendedUserTokenProvider adapter))
{
@ -458,12 +459,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
}
else
{
await this.SendInvokeResponseAsync(turnContext, cancellationToken, HttpStatusCode.NotFound).ConfigureAwait(false);
await this.SendInvokeResponseAsync(turnContext, HttpStatusCode.NotFound, null, cancellationToken).ConfigureAwait(false);
}
}
#pragma warning disable CA1031 // Do not catch general exception types (send a 500 if an error occurs).
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
await this.SendInvokeResponseAsync(turnContext, cancellationToken, HttpStatusCode.InternalServerError).ConfigureAwait(false);
await this.SendInvokeResponseAsync(turnContext, HttpStatusCode.InternalServerError, null, cancellationToken).ConfigureAwait(false);
}
}
else if (IsTokenExchangeRequestInvoke(turnContext))
@ -476,40 +479,37 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
{
await this.SendInvokeResponseAsync(
turnContext,
cancellationToken,
HttpStatusCode.BadRequest,
new TokenExchangeInvokeResponse()
{
Id = null,
ConnectionName = connectionName,
FailureDetail = "The bot received an InvokeActivity that is missing a TokenExchangeInvokeRequest value. This is required to be sent with the InvokeActivity.",
}).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
}
else if (tokenExchangeRequest.ConnectionName != connectionName)
{
await this.SendInvokeResponseAsync(
turnContext,
cancellationToken,
HttpStatusCode.BadRequest,
new TokenExchangeInvokeResponse()
{
Id = tokenExchangeRequest.Id,
ConnectionName = connectionName,
FailureDetail = "The bot received an InvokeActivity with a TokenExchangeInvokeRequest containing a ConnectionName that does not match the ConnectionName expected by the bot's active OAuthPrompt. Ensure these names match when sending the InvokeActivityInvalid ConnectionName in the TokenExchangeInvokeRequest",
}).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
}
else if (!(turnContext.Adapter is IExtendedUserTokenProvider adapter))
{
await this.SendInvokeResponseAsync(
turnContext,
cancellationToken,
HttpStatusCode.BadGateway,
new TokenExchangeInvokeResponse()
{
Id = tokenExchangeRequest.Id,
ConnectionName = connectionName,
FailureDetail = $"The bot's BotAdapter does not support token exchange operations. Ensure the bot's Adapter supports the {nameof(IExtendedUserTokenProvider)} interface.",
}).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
throw new InvalidOperationException("OAuthPrompt.Recognize(): not supported by the current adapter");
}
else
@ -527,7 +527,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
},
cancellationToken).ConfigureAwait(false);
}
#pragma warning disable CA1031 // Do not catch general exception types (see description below)
catch
#pragma warning restore CA1031 // Do not catch general exception types
{
// Ignore Exceptions
// If token exchange failed for any reason, tokenExchangeResponse above stays null , and hence we send back a failure invoke response to the caller.
@ -538,26 +540,24 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
{
await this.SendInvokeResponseAsync(
turnContext,
cancellationToken,
HttpStatusCode.Conflict,
new TokenExchangeInvokeResponse()
{
Id = tokenExchangeRequest.Id,
ConnectionName = connectionName,
FailureDetail = "The bot is unable to exchange token. Proceed with regular login.",
}).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
}
else
{
await this.SendInvokeResponseAsync(
turnContext,
cancellationToken,
HttpStatusCode.OK,
new TokenExchangeInvokeResponse()
{
Id = tokenExchangeRequest.Id,
ConnectionName = connectionName,
}).ConfigureAwait(false);
}, cancellationToken).ConfigureAwait(false);
result.Succeeded = true;
result.Value = new TokenResponse()
@ -623,7 +623,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Input
return true;
}
private async Task SendInvokeResponseAsync(ITurnContext turnContext, CancellationToken cancellationToken, HttpStatusCode statusCode, object body = null)
private async Task SendInvokeResponseAsync(ITurnContext turnContext, HttpStatusCode statusCode, object body, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync(
new Activity

Просмотреть файл

@ -11,7 +11,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
/// <summary>
/// load all lg resource and split them into different language group.
/// </summary>
#pragma warning disable CA1052 // Static holder types should be Static or NotInheritable (we can't change this without breaking binary compat)
public class LGResourceLoader
#pragma warning restore CA1052 // Static holder types should be Static or NotInheritable
{
public static Dictionary<string, IList<Resource>> GroupByLocale(ResourceExplorer resourceExplorer)
{
@ -51,7 +53,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
{
if (resourceMapping.ContainsKey(locale))
{
var resourcesWithEmptySuffix = allResources.Where(u => ParseLGFileName(u.Id).language == string.Empty);
var resourcesWithEmptySuffix = allResources.Where(u => ParseLGFileName(u.Id).language.Length == 0);
foreach (var resourceWithEmptySuffix in resourcesWithEmptySuffix)
{
var resourceName = resourceWithEmptySuffix.Id;
@ -77,14 +79,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
/// <returns>get the name and language.</returns>
public static (string prefix, string language) ParseLGFileName(string lgFileName)
{
if (string.IsNullOrEmpty(lgFileName) || !lgFileName.EndsWith(".lg"))
if (string.IsNullOrEmpty(lgFileName) || !lgFileName.EndsWith(".lg", StringComparison.Ordinal))
{
return (lgFileName, string.Empty);
}
var fileName = lgFileName.Substring(0, lgFileName.Length - ".lg".Length);
var lastDot = fileName.LastIndexOf(".");
var lastDot = fileName.LastIndexOf(".", StringComparison.Ordinal);
if (lastDot > 0)
{
return (fileName.Substring(0, lastDot), fileName.Substring(lastDot + 1));
@ -107,7 +109,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Generators
{
if (optionalLocales == null)
{
throw new ArgumentNullException();
throw new ArgumentNullException(nameof(optionalLocales));
}
if (optionalLocales.Contains(locale))

Просмотреть файл

@ -19,6 +19,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
/// <param name="data">data to bind to.</param>
/// <param name="cancellationToken">the <see cref="CancellationToken"/> for the task.</param>
/// <returns>object or text.</returns>
#pragma warning disable CA1716 // Identifiers should not match keywords (we can't change the template parameter name without breaking binary compat).
public abstract Task<object> GenerateAsync(DialogContext dialogContext, string template, object data, CancellationToken cancellationToken = default);
#pragma warning restore CA1716 // Identifiers should not match keywords
}
}

Просмотреть файл

@ -54,7 +54,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
lock (languageGeneratorManagers)
{
if (!languageGeneratorManagers.TryGetValue(resourceExplorer ?? throw new ArgumentNullException(nameof(resourceExplorer)), out var lgm))
if (!languageGeneratorManagers.TryGetValue(resourceExplorer ?? throw new InvalidOperationException($"Unable to get an instance of {nameof(resourceExplorer)}."), out var lgm))
{
lgm = new LanguageGeneratorManager(resourceExplorer);
languageGeneratorManagers[resourceExplorer] = lgm;

Просмотреть файл

@ -37,17 +37,17 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
defaultLanguages = new string[] { string.Empty };
}
var cultureCodes = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => c.IetfLanguageTag.ToLower()).ToList();
var cultureCodes = CultureInfo.GetCultures(CultureTypes.AllCultures).Select(c => c.IetfLanguageTag.ToLowerInvariant()).ToList();
var policy = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
foreach (var language in cultureCodes.Distinct())
{
var lang = language.ToLower();
var lang = language.ToLowerInvariant();
var fallback = new List<string>();
while (!string.IsNullOrEmpty(lang))
{
fallback.Add(lang);
var i = lang.LastIndexOf("-");
var i = lang.LastIndexOf("-", StringComparison.Ordinal);
if (i > 0)
{
lang = lang.Substring(0, i);
@ -58,7 +58,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
}
}
if (language == string.Empty)
if (language.Length == 0)
{
// here we set the default
fallback.AddRange(defaultLanguages);

Просмотреть файл

@ -52,7 +52,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Converters
if (reader.ValueType == typeof(string))
{
var id = (string)reader.Value;
if (id.StartsWith("="))
if (id.StartsWith("=", StringComparison.Ordinal))
{
result = new DialogExpression(id);
}
@ -60,9 +60,14 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Converters
{
try
{
result = new DialogExpression((Dialog)this.converter.ReadJson(new JsonTextReader(new StringReader($"\"{id}\"")), objectType, existingValue, serializer));
using (var jsonTextReader = new JsonTextReader(new StringReader($"\"{id}\"")))
{
result = new DialogExpression((Dialog)converter.ReadJson(jsonTextReader, objectType, existingValue, serializer));
}
}
#pragma warning disable CA1031 // Do not catch general exception types (return an empty if an exception happens).
catch (Exception)
#pragma warning restore CA1031 // Do not catch general exception types
{
result = new DialogExpression($"='{id}'");
}
@ -70,7 +75,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Converters
}
else
{
result = new DialogExpression((Dialog)this.converter.ReadJson(new JTokenReader(jToken), objectType, existingValue, serializer));
using (var jTokenReader = new JTokenReader(jToken))
{
result = new DialogExpression((Dialog)this.converter.ReadJson(jTokenReader, objectType, existingValue, serializer));
}
}
foreach (var observer in observers)

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using AdaptiveExpressions.Properties;
using Newtonsoft.Json.Linq;
@ -56,7 +57,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
{
if (value is string str)
{
if (!str.StartsWith("="))
if (!str.StartsWith("=", StringComparison.Ordinal))
{
// Resource Id's will be resolved to actual dialog value
// if it's not a = then we want to convert to a constant string expressions to represent a

Просмотреть файл

@ -27,7 +27,9 @@
<PropertyGroup>
<!-- These documentation warnings excludes should be removed as part of https://github.com/microsoft/botbuilder-dotnet/issues/4052 -->
<!-- SX1309: FieldNamesShouldBeginWithUnderscores should be fixed as part of https://github.com/microsoft/botframework-sdk/issues/5933 -->
<NoWarn>$(NoWarn);CS1591;SX1309</NoWarn>
<!-- CA2225: Operator overloads have named alternates, excluding for now, we should address this if we want to support other platforms than C#
see https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2225?view=vs-2019 .-->
<NoWarn>$(NoWarn);CS1591;SX1309;CA2225</NoWarn>
</PropertyGroup>
<ItemGroup>
@ -39,7 +41,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003" PrivateAssets="all" />
<PackageReference Include="AsyncUsageAnalyzers" Version="1.0.0-alpha003">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Bot.Builder.Dialogs.Declarative" Condition=" '$(IsBuildServer)' == '' " Version="$(LocalPackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs.Declarative" Condition=" '$(IsBuildServer)' != '' " Version="$(ReleasePackageVersion)" />
<PackageReference Include="Microsoft.Bot.Builder.LanguageGeneration" Condition=" '$(IsBuildServer)' == '' " Version="$(LocalPackageVersion)" />
@ -62,4 +71,4 @@
<ProjectReference Include="..\AdaptiveExpressions\AdaptiveExpressions.csproj" />
</ItemGroup>
</Project>
</Project>

Просмотреть файл

@ -65,7 +65,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// The input recognizers.
/// </value>
[JsonProperty("recognizers")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Recognizer> Recognizers { get; set; } = new List<Recognizer>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null)
{
@ -226,7 +228,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
private bool IsRedirect(string intent)
{
return intent.StartsWith(DeferPrefix);
return intent.StartsWith(DeferPrefix, StringComparison.Ordinal);
}
private string GetRedirectId(string intent)
@ -238,7 +240,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
{
if (this.Recognizers.Any(recognizer => string.IsNullOrEmpty(recognizer.Id)))
{
throw new ArgumentNullException("This recognizer requires that each recognizer in the set have an .Id value.");
throw new InvalidOperationException("This recognizer requires that each recognizer in the set have an .Id value.");
}
}
}

Просмотреть файл

@ -99,7 +99,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
}
}
}
#pragma warning disable CA1031 // Do not catch general exception types (trace the exception and continue).
catch (Exception err)
#pragma warning restore CA1031 // Do not catch general exception types
{
System.Diagnostics.Trace.TraceWarning(err.Message);
}

Просмотреть файл

@ -32,7 +32,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// Policy for languages fallback.
/// </value>
[JsonProperty("languagePolicy")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public LanguagePolicy LanguagePolicy { get; set; } = new LanguagePolicy();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets map of languages -> IRecognizer.
@ -41,7 +43,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// Map of languages -> IRecognizer.
/// </value>
[JsonProperty("recognizers")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public IDictionary<string, Recognizer> Recognizers { get; set; } = new Dictionary<string, Recognizer>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null)
{
@ -51,7 +55,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
policy.AddRange(targetpolicy);
}
if (activity.Locale != string.Empty && LanguagePolicy.TryGetValue(string.Empty, out string[] defaultPolicy))
if (activity.Locale.Length != 0 && LanguagePolicy.TryGetValue(string.Empty, out string[] defaultPolicy))
{
// we now explictly add defaultPolicy instead of coding that into target's policy
policy.AddRange(defaultPolicy);

Просмотреть файл

@ -41,7 +41,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// The input recognizers.
/// </value>
[JsonProperty("recognizers")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Recognizer> Recognizers { get; set; } = new List<Recognizer>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken = default, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null)
{

Просмотреть файл

@ -37,7 +37,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// Dictionary of patterns -> Intent names.
/// </value>
[JsonProperty("intents")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<IntentPattern> Intents { get; set; } = new List<IntentPattern>();
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets the entity recognizers.
@ -46,7 +48,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
/// The entity recognizers.
/// </value>
[JsonProperty("entities")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<EntityRecognizer> Entities { get; set; } = new List<EntityRecognizer>();
#pragma warning restore CA2227 // Collection properties should be read only
public override async Task<RecognizerResult> RecognizeAsync(DialogContext dialogContext, Activity activity, CancellationToken cancellationToken, Dictionary<string, string> telemetryProperties = null, Dictionary<string, double> telemetryMetrics = null)
{

Просмотреть файл

@ -56,13 +56,13 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Recognizers
// Map submitted values to a recognizer result, value : { "foo": 13} => Entities { "foo": [ 13 ] }
foreach (var property in value.Properties())
{
if (property.Name.ToLower() == "intent")
if (property.Name.ToLowerInvariant() == "intent")
{
recognized.Intents[property.Value.ToString()] = new IntentScore { Score = 1.0 };
}
else
{
if (recognized.Entities.Property(property.Name) == null)
if (recognized.Entities.Property(property.Name, StringComparison.Ordinal) == null)
{
recognized.Entities[property.Name] = new JArray(property.Value);
}

Просмотреть файл

@ -84,7 +84,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
// Copy parent $ properties like $entities
foreach (JProperty prop in schema.Properties())
{
if (prop.Name.StartsWith("$"))
if (prop.Name.StartsWith("$", StringComparison.Ordinal))
{
itemsSchema[prop.Name] = prop.Value;
}
@ -104,9 +104,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
{
foreach (JProperty prop in schema["properties"])
{
if (!prop.Name.StartsWith("$"))
if (!prop.Name.StartsWith("$", StringComparison.Ordinal))
{
var newPath = path == string.Empty ? prop.Name : $"{path}.{prop.Name}";
var newPath = path.Length == 0 ? prop.Name : $"{path}.{prop.Name}";
children.Add(CreateProperty((JObject)prop.Value, newPath));
}
}
@ -129,7 +129,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive
var newPath = path;
if (grand != null && grand is JProperty grandProp && grandProp.Name == "properties")
{
newPath = path == string.Empty ? prop.Name : $"{path}.{prop.Name}";
newPath = path.Length == 0 ? prop.Name : $"{path}.{prop.Name}";
}
if (stop = Analyze(newPath, prop.Value, analyzer))

Просмотреть файл

@ -23,7 +23,8 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Selectors
private bool _evaluate;
private Random _rand;
private int _seed = -1;
private readonly object _objectLock = new object();
/// <summary>
/// Gets or sets optional seed for random number generator.
/// </summary>
@ -74,7 +75,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Selectors
if (candidates.Count > 0)
{
int selection;
lock (this)
lock (_objectLock)
{
selection = _rand.Next(candidates.Count);
}

Просмотреть файл

@ -38,10 +38,10 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Templates
{
if (string.IsNullOrEmpty(this.Template))
{
throw new ArgumentNullException(nameof(this.Template));
throw new InvalidOperationException($"The {nameof(this.Template)} property can't be empty.");
}
LanguageGenerator languageGenerator = dialogContext.Services.Get<LanguageGenerator>();
var languageGenerator = dialogContext.Services.Get<LanguageGenerator>();
if (languageGenerator != null)
{
var result = await languageGenerator.GenerateAsync(

Просмотреть файл

@ -10,7 +10,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
/// <summary>
/// Extension method for <see cref="DialogContext"/> provides <see cref="DebugSupport"/>.
/// </summary>
#pragma warning disable CA1724 // Type names should not match namespaces (by design and we can't change this without breaking binary compat)
public static partial class Extensions
#pragma warning restore CA1724 // Type names should not match namespaces
{
public static async Task DebuggerStepAsync(this DialogContext context, OnCondition conditional, DialogEvent dialogEvent, CancellationToken cancellationToken)
{

Просмотреть файл

@ -32,7 +32,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
/// </summary>
/// <value>List of intent names that must be in the chooseIntent to match.</value>
[JsonProperty("intents")]
#pragma warning disable CA2227 // Collection properties should be read only
public List<string> Intents { get; set; } = new List<string>();
#pragma warning restore CA2227 // Collection properties should be read only
public override Expression GetExpression()
{

Просмотреть файл

@ -33,14 +33,18 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
/// </summary>
/// <value>List of property names.</value>
[JsonProperty("properties")]
#pragma warning disable CA2227 // Collection properties should be read only
public List<string> Properties { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
/// <summary>
/// Gets or sets the entities being chosen between to filter events.
/// </summary>
/// <value>List of entity names.</value>
[JsonProperty("entities")]
#pragma warning disable CA2227 // Collection properties should be read only
public List<string> Entities { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
public override string GetIdentity()
=> $"{this.GetType().Name}([{string.Join(",", this.Properties)}], {this.Entities})";

Просмотреть файл

@ -63,7 +63,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
/// The actions to add to the plan when the rule constraints are met.
/// </value>
[JsonProperty("actions")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<Dialog> Actions { get; set; } = new List<Dialog>();
#pragma warning restore CA2227 // Collection properties should be read only
[JsonIgnore]
public virtual SourceRange Source => DebugSupport.SourceMap.TryGetValue(this, out var range) ? range : null;

Просмотреть файл

@ -48,7 +48,9 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
/// Entities which must be recognized for this rule to trigger.
/// </value>
[JsonProperty("entities")]
#pragma warning disable CA2227 // Collection properties should be read only (we can't change this without breaking binary compat)
public List<string> Entities { get; set; }
#pragma warning restore CA2227 // Collection properties should be read only
public override string GetIdentity()
{
@ -60,7 +62,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
// add constraints for the intents property
if (string.IsNullOrEmpty(this.Intent))
{
throw new ArgumentNullException(nameof(this.Intent));
throw new InvalidOperationException($"The {nameof(this.Intent)} property is null or empty.");
}
var intentExpression = Expression.Parse($"{TurnPath.Recognized}.intent == '{this.Intent.TrimStart('#')}'");
@ -72,7 +74,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Adaptive.Conditions
intentExpression,
Expression.AndExpression(this.Entities.Select(entity =>
{
if (entity.StartsWith("@") || entity.StartsWith(TurnPath.Recognized, StringComparison.InvariantCultureIgnoreCase))
if (entity.StartsWith("@", StringComparison.Ordinal) || entity.StartsWith(TurnPath.Recognized, StringComparison.InvariantCultureIgnoreCase))
{
return Expression.Parse($"exists({entity})");
}

Просмотреть файл

@ -102,9 +102,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Choices
if (token != null)
{
token.End = end;
#pragma warning disable CA1308 // Normalize strings to uppercase (the normalized token should be lowercase, ignoring)
token.Normalized = token.Text.ToLowerInvariant();
#pragma warning restore CA1308 // Normalize strings to uppercase
tokens.Add(token);
}
}

Просмотреть файл

@ -585,9 +585,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Memory
void CheckChildren(string property, object instance)
{
// Add new child segment
#pragma warning disable CA1308 // Normalize strings to uppercase (we assume properties are lowercase).
trackedPath += "_" + property.ToLowerInvariant();
#pragma warning restore CA1308 // Normalize strings to uppercase
Update();
if (instance is object child)
{

Просмотреть файл

@ -179,9 +179,7 @@ namespace Microsoft.Bot.Builder.Dialogs.Prompts
/// <returns>Normalized locale.</returns>
public static string MapToNearestLanguage(string cultureCode)
{
#pragma warning disable CA1308 // Normalize strings to uppercase (culture codes are expected to be in lowercase, ignoring)
cultureCode = cultureCode.ToLowerInvariant();
#pragma warning restore CA1308 // Normalize strings to uppercase
if (SupportedLocales.All(o => o != cultureCode))
{

Просмотреть файл

@ -16,7 +16,6 @@ namespace Microsoft.Bot.Builder
public class ActivityFactory
#pragma warning restore CA1052 // Static holder types should be Static or NotInheritable
{
#pragma warning disable CA1308 // Normalize strings to uppercase (LG is heavily invested in lowercase, ignoring this rule in this class)
private const string LGType = "lgType";
private const string AdaptiveCardType = "application/vnd.microsoft.card.adaptive";
@ -407,6 +406,5 @@ namespace Microsoft.Bot.Builder
return type?.ToLowerInvariant() ?? string.Empty;
}
#pragma warning restore CA1308 // Normalize strings to uppercase
}
}

Просмотреть файл

@ -126,10 +126,8 @@ namespace Microsoft.Bot.Builder.Adapters
ChannelId = "test",
ServiceUrl = "https://test.com",
Conversation = new ConversationAccount(false, name, name),
#pragma warning disable CA1308 // Normalize strings to uppercase (it is safe to use lowercase here, this is just for display purposes)
User = new ChannelAccount(id: user.ToLowerInvariant(), name: user),
Bot = new ChannelAccount(id: bot.ToLowerInvariant(), name: bot),
#pragma warning restore CA1308 // Normalize strings to uppercase
Locale = "en-us"
};
}

Просмотреть файл

@ -179,10 +179,8 @@ namespace Microsoft.Bot.Builder.Integration.AspNet.WebApi
{
if (!await CredentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
{
#pragma warning disable CA1308 // Normalize strings to uppercase (header names come in lowercase, ignoring)
var authHeader = httpRequest.Headers.GetValues(AuthHeaderName.ToLowerInvariant()).FirstOrDefault();
var channelId = httpRequest.Headers.GetValues(ChannelIdHeaderName.ToLowerInvariant()).FirstOrDefault();
#pragma warning restore CA1308 // Normalize strings to uppercase
if (string.IsNullOrWhiteSpace(authHeader))
{