From bbbfabbb3cac35d496d6658702866b469c041f90 Mon Sep 17 00:00:00 2001 From: Rob Chambers Date: Thu, 28 Mar 2024 12:05:12 -0700 Subject: [PATCH] Robch/2403 mar23 nullable (#250) * update details\console stuff to be nullable enabled * GetOrEmpty * more GetOrEmpty * parsers are nullable clean now * more helpers work nullable * more GetOrEmpty and nullable work * more helpers and named values work with nullable * more token things work with nullable * more parsers work with nullable * more parsers and values work with nullable * commands work with nullable (mostly) * more nullable works * more nullable * a few more ... * update stopwatch output for telemetry * better refactoring of AiProgram.Main * all nullable warnings in common.csproj except ConsoleGui stuff for python wrapped and azcli wrapped are now fixed * fix bug with program name length and environment named values * much of test framework nullable warnings removed * finished test framework nullable warning fixes * more updates for nullable (wip) * more speech extension nullable warning fixes --- src/ai/Program_AI.cs | 60 ++- src/ai/commands/chat_command.cs | 21 +- src/ai/commands/dev_command.cs | 13 +- src/ai/commands/eval_command.cs | 3 +- src/ai/commands/init_command.cs | 59 ++- src/ai/commands/language_command.cs | 3 +- .../commands/parsers/init_command_parser.cs | 3 +- .../parsers/scenario_wizard_command_parser.cs | 3 +- src/ai/commands/scenario_wizard_command.cs | 13 +- src/ai/commands/search_command.cs | 13 +- src/ai/commands/service_command.cs | 13 +- src/ai/commands/speech_command.cs | 3 +- src/ai/commands/test_command.cs | 13 +- src/ai/commands/tool_command.cs | 3 +- src/ai/commands/version_command.cs | 21 +- src/ai/commands/vision_command.cs | 3 +- src/ai/helpers/output_helper_base.cs | 44 +-- src/clis/vz/commands/face_command.cs | 3 +- src/clis/vz/commands/image_command.cs | 47 ++- src/clis/vz/commands/person_command.cs | 31 +- src/common/Program.cs | 48 +-- .../Telemetry/Events/InitTelemetryEvent.cs | 8 +- src/common/Telemetry/ITelemetry.cs | 14 +- src/common/common.csproj | 1 + ...SdkConsoleGui_PickOrCreateAiHubResource.cs | 12 +- src/common/details/commands/command.cs | 114 +++--- src/common/details/commands/command_values.cs | 10 +- src/common/details/commands/config_command.cs | 22 +- .../commands/parsers/command_parser.cs | 12 +- .../commands/parsers/help_command_parser.cs | 34 +- src/common/details/commands/runjob_command.cs | 63 ++-- src/common/details/console/ColorHelpers.cs | 2 +- src/common/details/console/ConsoleHelpers.cs | 14 +- src/common/details/console/gui/Screen.cs | 12 +- src/common/details/console/gui/Window.cs | 18 +- .../details/console/gui/controls/Control.cs | 2 +- .../console/gui/controls/EditBoxControl.cs | 6 +- .../console/gui/controls/EditBoxQuickEdit.cs | 6 +- .../console/gui/controls/HelpViewer.cs | 12 +- .../console/gui/controls/ListBoxControl.cs | 6 +- .../console/gui/controls/ListBoxPicker.cs | 6 +- .../console/gui/controls/ScrollingControl.cs | 2 +- .../gui/controls/SpeedSearchListBoxControl.cs | 24 +- .../console/gui/controls/TextViewerControl.cs | 2 +- .../gui/controls/VirtualListBoxControl.cs | 2 +- .../console/gui_helpers/ask_prompt_helper.cs | 2 +- .../gui_helpers/name_picker_helpers.cs | 42 +-- .../details/helpers/config_set_helpers.cs | 98 +++-- src/common/details/helpers/expect_helper.cs | 64 ++-- src/common/details/helpers/file_helpers.cs | 178 +++++---- src/common/details/helpers/http_helpers.cs | 42 +-- src/common/details/helpers/json_helpers.cs | 24 +- src/common/details/helpers/log_helpers.cs | 2 +- src/common/details/helpers/process_helpers.cs | 51 +-- src/common/details/helpers/python_runner.cs | 33 +- .../details/helpers/try_catch_helpers.cs | 12 +- src/common/details/helpers/url_helpers.cs | 41 ++- .../named_values/environment_named_values.cs | 16 +- .../named_values/named_value_tokens.cs | 10 +- .../details/named_values/named_values.cs | 60 +-- .../parsers/for_each_token_parser.cs | 8 +- .../parsers/input_wildcard_token_parser.cs | 2 +- .../parsers/named_value_token_parser.cs | 36 +- .../named_value_token_parser_helpers.cs | 6 +- .../parsers/option_x_token_parser.cs | 2 +- .../parsers/replace_for_each_token_parser.cs | 8 +- .../sources/cmd_line_token_source.cs | 10 +- .../sources/ini_line_token_source.cs | 10 +- .../sources/tsv_row_token_source.cs | 10 +- .../named_values/tokens/arg_x_token.cs | 2 +- .../tokens/conatins_option_x_token.cs | 2 +- .../tokens/file_option_x_token.cs | 2 +- .../tokens/files_option_x_token.cs | 2 +- .../tokens/named_value_token_data.cs | 8 +- .../tokens/named_value_token_data_helpers.cs | 2 +- .../tokens/remove_option_x_token.cs | 2 +- .../tokens/search_option_x_token.cs | 2 +- .../tokens/test_option_x_token.cs | 2 +- .../tokens/tests_option_x_token.cs | 2 +- .../commands/base/recognize_commands_base.cs | 78 ++-- .../commands/batch_command.cs | 87 +++-- .../conversation_transcription_command.cs | 118 +++--- .../custom_speech_recognition_command.cs | 201 +++++----- .../commands/dialog_command.cs | 18 +- .../commands/intent_command.cs | 128 ++++--- .../commands/meeting_transcription_command.cs | 114 +++--- ...ustom_speech_recognition_command_parser.cs | 3 +- .../commands/parsers/dialog_command_parser.cs | 3 +- .../commands/parsers/webjob_command_parser.cs | 3 +- .../commands/profile_command.cs | 19 +- .../commands/recognize_command.cs | 124 +++---- .../commands/synthesize_command.cs | 85 +++-- .../commands/translate_command.cs | 112 +++--- .../commands/webjob_command.cs | 39 +- .../speech_extension/helpers/audio_helpers.cs | 16 +- .../helpers/caption_helper.cs | 16 +- .../helpers/config_helpers.cs | 12 +- .../helpers/connection_helpers.cs | 6 +- .../speech_extension/helpers/output_helper.cs | 346 +++++++++--------- .../template_extension/TemplateFactory.cs | 4 +- .../testframework/JunitXmlTestReporter.cs | 30 +- src/extensions/testframework/Logger.cs | 2 +- .../testframework/TrxXmlTestReporter.cs | 4 +- .../testframework/YamlEnvHelpers.cs | 2 +- src/extensions/testframework/YamlHelpers.cs | 2 +- .../testframework/YamlNodeExtensions.cs | 18 +- .../testframework/YamlTagHelpers.cs | 28 +- .../testframework/YamlTestCaseFilter.cs | 4 +- .../testframework/YamlTestCaseParser.cs | 131 ++++--- .../testframework/YamlTestCaseRunner.cs | 81 ++-- .../testframework/YamlTestConfigHelpers.cs | 10 +- .../testframework/YamlTestFramework.csproj | 1 + .../YamlTestFrameworkConsoleHost.cs | 4 +- .../testframework/YamlTestProperties.cs | 2 +- 114 files changed, 1764 insertions(+), 1704 deletions(-) diff --git a/src/ai/Program_AI.cs b/src/ai/Program_AI.cs index 677abc5c..b83c2324 100644 --- a/src/ai/Program_AI.cs +++ b/src/ai/Program_AI.cs @@ -17,49 +17,39 @@ public class AiProgram { static async Task Main(string[] args) { - IProgramData data = null; + bool isDebug = args.Length > 0 && args[0] == "debug"; + if (isDebug) Console.WriteLine($"StopWatch: Started at {DateTime.Now}"); + Stopwatch stopwatch = new Stopwatch(); - int exitCode = int.MinValue; + stopwatch.Start(); - try - { - bool isDebug = args.Length > 0 && args[0] == "debug"; - if (isDebug) - { - Console.WriteLine($"StopWatch: Started at {DateTime.Now}"); - } + var exitCode = TryCatchHelpers.TryCatchNoThrow(() => Program.Main(new AiProgramData(), args), -1, out var ex); - stopwatch.Start(); + stopwatch.Stop(); + var elapsed = stopwatch.Elapsed; + if (isDebug) Console.WriteLine($"StopWatch: Stopped at {DateTime.Now} ({GetStopWatchElapsedAsString(elapsed)})"); - data = new AiProgramData(); - exitCode = Program.Main(data, args); - stopwatch.Stop(); + stopwatch.Restart(); + await LogExitEventAsync(elapsed, exitCode); - if (isDebug) - { - Console.WriteLine($"StopWatch: Stopped at {DateTime.Now} ({GetStopWatchElapsedAsString(stopwatch.Elapsed)})"); - } + stopwatch.Stop(); + if (isDebug) Console.WriteLine($"StopWatch: Telemetry completed at {DateTime.Now} ({GetStopWatchElapsedAsString(stopwatch.Elapsed)})"); - return exitCode; - } - catch (Exception) - { - exitCode = -1; - throw; - } - finally + if (ex != null) throw ex; + return exitCode; + } + + static async Task LogExitEventAsync(TimeSpan elapsed, int exitCode) + { + if (Program.Telemetry != null) { - if (data?.Telemetry != null) + Program.Telemetry.LogEvent(new ExitedTelemetryEvent() { - data.Telemetry.LogEvent(new ExitedTelemetryEvent() - { - ExitCode = exitCode, - Elapsed = stopwatch.Elapsed - }); - - await data.Telemetry.DisposeAsync() - .ConfigureAwait(false); - } + ExitCode = exitCode, + Elapsed = elapsed + }); + + await Program.Telemetry.DisposeAsync(); } } diff --git a/src/ai/commands/chat_command.cs b/src/ai/commands/chat_command.cs index c390a3c3..9075c629 100644 --- a/src/ai/commands/chat_command.cs +++ b/src/ai/commands/chat_command.cs @@ -27,9 +27,8 @@ namespace Azure.AI.Details.Common.CLI { public class ChatCommand : Command { - internal ChatCommand(ICommandValues values) + internal ChatCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -1067,11 +1066,11 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); // var id = _values["chat.input.id"]; - // _output.EnsureOutputAll("chat.input.id", id); - // _output.EnsureOutputEach("chat.input.id", id); + // _output!.EnsureOutputAll("chat.input.id", id); + // _output!.EnsureOutputEach("chat.input.id", id); _lock = new SpinLock(); _lock.StartLock(); @@ -1079,23 +1078,23 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet = false; private readonly bool _verbose = false; private AzureEventSourceListener _azureEventSourceListener; - // OutputHelper _output = null; - // DisplayHelper _display = null; + // OutputHelper? _output = null; + // DisplayHelper? _display = null; #nullable enable private int? TryParse(string? s, int? defaultValue) diff --git a/src/ai/commands/dev_command.cs b/src/ai/commands/dev_command.cs index 83dff8da..cba677fe 100644 --- a/src/ai/commands/dev_command.cs +++ b/src/ai/commands/dev_command.cs @@ -15,9 +15,8 @@ namespace Azure.AI.Details.Common.CLI { public class DevCommand : Command { - internal DevCommand(ICommandValues values) + internal DevCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", false); } @@ -206,7 +205,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -214,16 +213,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet; private readonly bool _verbose; } diff --git a/src/ai/commands/eval_command.cs b/src/ai/commands/eval_command.cs index 45e5072d..60a44373 100644 --- a/src/ai/commands/eval_command.cs +++ b/src/ai/commands/eval_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class EvalCommand : Command { - internal EvalCommand(ICommandValues values) + internal EvalCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/ai/commands/init_command.cs b/src/ai/commands/init_command.cs index 2dd13a64..d7e68618 100644 --- a/src/ai/commands/init_command.cs +++ b/src/ai/commands/init_command.cs @@ -22,9 +22,8 @@ namespace Azure.AI.Details.Common.CLI { public class InitCommand : Command { - public InitCommand(ICommandValues values) + public InitCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -533,20 +532,20 @@ private async Task DoInitRootOpenAi(bool interactive, bool skipChat = false, boo private async Task DoInitOpenAi(bool interactive, bool skipChat = false, bool allowSkipChat = true, bool skipEmbeddings = false, bool allowSkipEmbeddings = true, bool skipEvaluations = false, bool allowSkipEvaluations = true) { var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values, ""); - var regionFilter = _values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = _values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = _values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var regionFilter = _values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = _values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = _values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = _values.GetOrDefault("init.service.cognitiveservices.resource.kind", "OpenAI;AIServices"); var sku = _values.GetOrDefault("init.service.cognitiveservices.resource.sku", Program.CognitiveServiceResourceSku); var yes = _values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); - var chatDeploymentFilter = _values.GetOrDefault("init.chat.model.deployment.name", ""); - var embeddingsDeploymentFilter = _values.GetOrDefault("init.embeddings.model.deployment.name", ""); - var evaluationsDeploymentFilter = _values.GetOrDefault("init.evaluation.model.deployment.name", ""); + var chatDeploymentFilter = _values.GetOrEmpty("init.chat.model.deployment.name"); + var embeddingsDeploymentFilter = _values.GetOrEmpty("init.embeddings.model.deployment.name"); + var evaluationsDeploymentFilter = _values.GetOrEmpty("init.evaluation.model.deployment.name"); - var chatModelFilter = _values.GetOrDefault("init.chat.model.name", ""); - var embeddingsModelFilter = _values.GetOrDefault("init.embeddings.model.name", ""); - var evaluationsModelFilter = _values.GetOrDefault("init.evaluation.model.name", ""); + var chatModelFilter = _values.GetOrEmpty("init.chat.model.name"); + var embeddingsModelFilter = _values.GetOrEmpty("init.embeddings.model.name"); + var evaluationsModelFilter = _values.GetOrEmpty("init.evaluation.model.name"); var resource = await AzCliConsoleGui.PickOrCreateAndConfigCognitiveServicesOpenAiKindResource(_values, interactive, subscriptionId, regionFilter, groupFilter, resourceFilter, kind, sku, yes, skipChat, allowSkipChat, skipEmbeddings, allowSkipEmbeddings, skipEvaluations, allowSkipEvaluations, chatDeploymentFilter, embeddingsDeploymentFilter, evaluationsDeploymentFilter, chatModelFilter, embeddingsModelFilter, evaluationsModelFilter); _values.Reset("service.openai.deployments.picked", "true"); @@ -571,10 +570,10 @@ private async Task DoInitRootCognitiveServicesAIServicesKind(bool interactive) private async Task DoInitCognitiveServicesAIServicesKind(bool interactive) { - var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values, ""); - var regionFilter = _values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = _values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = _values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values); + var regionFilter = _values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = _values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = _values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = _values.GetOrDefault("init.service.cognitiveservices.resource.kind", "AIServices"); var sku = _values.GetOrDefault("init.service.cognitiveservices.resource.sku", Program.CognitiveServiceResourceSku); var yes = _values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); @@ -602,9 +601,9 @@ private async Task DoInitRootCognitiveServicesCognitiveServicesKind(bool interac private async Task DoInitCognitiveServicesCognitiveServicesKind(bool interactive) { var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values, ""); - var regionFilter = _values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = _values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = _values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var regionFilter = _values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = _values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = _values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = _values.GetOrDefault("init.service.cognitiveservices.resource.kind", "CognitiveServices"); var sku = _values.GetOrDefault("init.service.cognitiveservices.resource.sku", Program.CognitiveServiceResourceSku); var yes = _values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); @@ -630,7 +629,7 @@ private async Task DoInitRootSearch(bool interactive) private async Task DoInitSearch(bool interactive, bool allowSkipSearch = true) { var subscription = SubscriptionToken.Data().GetOrDefault(_values, ""); - var location = _values.GetOrDefault("service.resource.region.name", ""); + var location = _values.GetOrEmpty("service.resource.region.name"); var groupName = ResourceGroupNameToken.Data().GetOrDefault(_values, ""); var smartName = ResourceNameToken.Data().GetOrDefault(_values); @@ -656,9 +655,9 @@ private async Task DoInitRootVision(bool interactive) private async Task DoInitSpeech(bool interactive) { var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values, ""); - var regionFilter = _values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = _values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = _values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var regionFilter = _values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = _values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = _values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = _values.GetOrDefault("init.service.cognitiveservices.resource.kind", "SpeechServices"); var sku = _values.GetOrDefault("init.service.cognitiveservices.resource.sku", "S0"); var yes = _values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); @@ -671,9 +670,9 @@ private async Task DoInitSpeech(bool interactive) private async Task DoInitVision(bool interactive) { var subscriptionId = SubscriptionToken.Data().GetOrDefault(_values, ""); - var regionFilter = _values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = _values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = _values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var regionFilter = _values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = _values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = _values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = _values.GetOrDefault("init.service.cognitiveservices.resource.kind", "ComputerVision"); var sku = _values.GetOrDefault("init.service.cognitiveservices.resource.sku", "S0"); var yes = _values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); @@ -712,7 +711,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -720,16 +719,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet = false; private readonly bool _verbose = false; } diff --git a/src/ai/commands/language_command.cs b/src/ai/commands/language_command.cs index 584003b4..2d580a70 100644 --- a/src/ai/commands/language_command.cs +++ b/src/ai/commands/language_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class LanguageCommand : Command { - internal LanguageCommand(ICommandValues values) + internal LanguageCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/ai/commands/parsers/init_command_parser.cs b/src/ai/commands/parsers/init_command_parser.cs index ea11153f..860da8a4 100644 --- a/src/ai/commands/parsers/init_command_parser.cs +++ b/src/ai/commands/parsers/init_command_parser.cs @@ -67,7 +67,8 @@ private static INamedValueTokenParser[] GetCommandParsers(ICommandValues values) return initCommandParsers; } - return null; + values.AddThrowError("ERROR:", $"Unknown command: {commandName}"); + return Array.Empty(); } #region private data diff --git a/src/ai/commands/parsers/scenario_wizard_command_parser.cs b/src/ai/commands/parsers/scenario_wizard_command_parser.cs index 2aa883e4..f689561c 100644 --- a/src/ai/commands/parsers/scenario_wizard_command_parser.cs +++ b/src/ai/commands/parsers/scenario_wizard_command_parser.cs @@ -36,7 +36,8 @@ private static INamedValueTokenParser[] GetCommandParsers(ICommandValues values) return ScenarioWizardCommandParsers; } - return null; + values.AddThrowError("ERROR:", $"Unknown command: {commandName}"); + return Array.Empty(); } #region private data diff --git a/src/ai/commands/scenario_wizard_command.cs b/src/ai/commands/scenario_wizard_command.cs index d91db75e..1b5c059b 100644 --- a/src/ai/commands/scenario_wizard_command.cs +++ b/src/ai/commands/scenario_wizard_command.cs @@ -22,9 +22,8 @@ namespace Azure.AI.Details.Common.CLI { public class ScenarioWizardCommand : Command { - internal ScenarioWizardCommand(ICommandValues values) + internal ScenarioWizardCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -422,7 +421,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -430,16 +429,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet = false; private readonly bool _verbose = false; } diff --git a/src/ai/commands/search_command.cs b/src/ai/commands/search_command.cs index ef823917..489211ca 100644 --- a/src/ai/commands/search_command.cs +++ b/src/ai/commands/search_command.cs @@ -35,9 +35,8 @@ namespace Azure.AI.Details.Common.CLI { public class SearchCommand : Command { - internal SearchCommand(ICommandValues values) + internal SearchCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -661,7 +660,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -669,15 +668,15 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet = false; private readonly bool _verbose = false; } diff --git a/src/ai/commands/service_command.cs b/src/ai/commands/service_command.cs index a81eaf18..c34d9374 100644 --- a/src/ai/commands/service_command.cs +++ b/src/ai/commands/service_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class ServiceCommand : Command { - internal ServiceCommand(ICommandValues values) + internal ServiceCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -299,7 +298,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -307,16 +306,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private bool _quiet = false; private bool _verbose = false; } diff --git a/src/ai/commands/speech_command.cs b/src/ai/commands/speech_command.cs index 1764a7dc..f4393604 100644 --- a/src/ai/commands/speech_command.cs +++ b/src/ai/commands/speech_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class SpeechCommand : Command { - internal SpeechCommand(ICommandValues values) + internal SpeechCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/ai/commands/test_command.cs b/src/ai/commands/test_command.cs index 1158849a..393ec861 100644 --- a/src/ai/commands/test_command.cs +++ b/src/ai/commands/test_command.cs @@ -17,9 +17,8 @@ namespace Azure.AI.Details.Common.CLI { public class TestCommand : Command { - internal TestCommand(ICommandValues values) + internal TestCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", false); } @@ -222,7 +221,7 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); _lock = new SpinLock(); _lock.StartLock(); @@ -230,16 +229,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet; private readonly bool _verbose; } diff --git a/src/ai/commands/tool_command.cs b/src/ai/commands/tool_command.cs index 939e6f3e..c9281b30 100644 --- a/src/ai/commands/tool_command.cs +++ b/src/ai/commands/tool_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class ToolCommand : Command { - internal ToolCommand(ICommandValues values) + internal ToolCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/ai/commands/version_command.cs b/src/ai/commands/version_command.cs index 1deedeb7..bc2b6a94 100644 --- a/src/ai/commands/version_command.cs +++ b/src/ai/commands/version_command.cs @@ -17,9 +17,8 @@ namespace Azure.AI.Details.Common.CLI { public class VersionCommand : Command { - internal VersionCommand(ICommandValues values) + internal VersionCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -59,11 +58,11 @@ private void StartCommand() // _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); // var id = _values["chat.input.id"]; - // _output.EnsureOutputAll("chat.input.id", id); - // _output.EnsureOutputEach("chat.input.id", id); + // _output!.EnsureOutputAll("chat.input.id", id); + // _output!.EnsureOutputEach("chat.input.id", id); _lock = new SpinLock(); _lock.StartLock(); @@ -71,23 +70,23 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); LogHelpers.EnsureStopLogFile(_values); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); _stopEvent.Set(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private readonly bool _quiet = false; private readonly bool _verbose = false; // private AzureEventSourceListener _azureEventSourceListener; - // OutputHelper _output = null; - // DisplayHelper _display = null; + // OutputHelper? _output = null; + // DisplayHelper? _display = null; private void DoVersionUpdate() { diff --git a/src/ai/commands/vision_command.cs b/src/ai/commands/vision_command.cs index cb3871c9..1607f6c8 100644 --- a/src/ai/commands/vision_command.cs +++ b/src/ai/commands/vision_command.cs @@ -14,9 +14,8 @@ namespace Azure.AI.Details.Common.CLI { public class VisionCommand : Command { - internal VisionCommand(ICommandValues values) + internal VisionCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/ai/helpers/output_helper_base.cs b/src/ai/helpers/output_helper_base.cs index 06bc625b..af65ae14 100644 --- a/src/ai/helpers/output_helper_base.cs +++ b/src/ai/helpers/output_helper_base.cs @@ -56,7 +56,7 @@ public void StopOutput() FlushOutputAllCache(); FlushOutputPropertyCache(); FlushOutputZipFile(); - _lock.StopLock(); + _lock!.StopLock(); } } @@ -65,15 +65,15 @@ private bool ShouldCacheProperty() return false; // TODO } - public void EnsureCacheProperty(string name, string value) + public void EnsureCacheProperty(string name, string? value) { - if (ShouldCacheProperty()) CacheProperty(name, value); + if (ShouldCacheProperty() && value != null) CacheProperty(name, value); } private void CacheProperty(string name, string value) { EnsureInitPropertyCache(); - _propertyCache.Add(name, value); + _propertyCache!.Add(name, value); } private void EnsureInitPropertyCache() @@ -127,7 +127,7 @@ public void EnsureOutputAll(string name, string value) EnsureOutputAll('\n', name, "{0}", value); } - public string GetAllOutput(string name, string defaultValue = null) + public string? GetAllOutput(string name, string? defaultValue = null) { if (_outputAllCache == null || !_outputAllCache.ContainsKey(name)) return defaultValue; @@ -197,7 +197,7 @@ private string GetOutputAllFileName() { var file = _values.GetOrDefault("output.all.file.name", "output.{run.time}." + GetOutputAllFileType()); - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -206,7 +206,7 @@ private string GetOutputAllFileName() var time = DateTime.Now.ToFileTime().ToString(); if (file.Contains("{time}")) file = file.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -259,7 +259,7 @@ private void OutputAllTsvFileRow(string file, string[] columns) StringBuilder sb = new StringBuilder(); foreach (var column in columns) { - var value = GetAllOutput(column, ""); + var value = GetAllOutput(column, "")!; sb.Append(EncodeOutputValue(value)); sb.Append('\t'); } @@ -309,7 +309,7 @@ public void EnsureOutputEach(string name, string format, params object[] arg) private void AddOutputEachCache(string name, string value) { EnsureInitOutputEachCache(); - _outputEachCache[name] = value; + _outputEachCache![name] = value; } private void EnsureInitOutputEachCache() @@ -340,7 +340,7 @@ private void FlushOutputEachCacheStage2(bool overwrite = false) if (!_outputEach) return; overwrite = overwrite && _values.GetOrDefault("output.overwrite", false); - if (overwrite) File.Delete(_outputEachFileName); + if (overwrite) File.Delete(_outputEachFileName!); switch (_outputEachFileType) { @@ -361,7 +361,7 @@ private string GetOutputEachFileName() { var file = _values.GetOrDefault("output.each.file.name", "each.{run.time}." + GetOutputEachFileType()); - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -370,7 +370,7 @@ private string GetOutputEachFileName() var time = DateTime.Now.ToFileTime().ToString(); if (file.Contains("{time}")) file = file.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -392,15 +392,15 @@ private string[] GetOutputEachColumns() private void OutputEachJsonFile() { - var json = JsonHelpers.GetJsonArrayText(_outputEachCache2) + Environment.NewLine; - FileHelpers.AppendAllText(_outputEachFileName, json, Encoding.UTF8); + var json = JsonHelpers.GetJsonArrayText(_outputEachCache2!) + Environment.NewLine; + FileHelpers.AppendAllText(_outputEachFileName!, json, Encoding.UTF8); } private void OutputEachTsvFile() { var columns = GetOutputEachColumns(); - EnsureOutputEachTsvFileHeader(_outputEachFileName, columns); - OutputEachTsvFileRow(_outputEachFileName, columns); + EnsureOutputEachTsvFileHeader(_outputEachFileName!, columns); + OutputEachTsvFileRow(_outputEachFileName!, columns); } private void EnsureOutputEachTsvFileHeader(string file, string[] columns) @@ -448,7 +448,7 @@ private void FlushOutputZipFile() { if (!_outputAll && !_outputEach) return; - var zipFileName = _values.GetOrDefault("output.zip.file", ""); + var zipFileName = _values.GetOrEmpty("output.zip.file"); if (string.IsNullOrEmpty(zipFileName)) return; TryCatchHelpers.TryCatchRetry(() => @@ -481,7 +481,7 @@ private void AddToZip(ZipArchive zip, string file) private SpinLock _lock = new SpinLock(); - private Dictionary _propertyCache = null; + private Dictionary? _propertyCache = null; private bool _outputAll = false; private string _outputAllFileName = null; @@ -491,9 +491,9 @@ private void AddToZip(ZipArchive zip, string file) private bool _outputEach = false; private bool _overwriteEach = false; - private string _outputEachFileName = null; - private string _outputEachFileType = null; - private Dictionary _outputEachCache; - private List> _outputEachCache2; + private string? _outputEachFileName = null; + private string? _outputEachFileType = null; + private Dictionary? _outputEachCache; + private List>? _outputEachCache2; } } diff --git a/src/clis/vz/commands/face_command.cs b/src/clis/vz/commands/face_command.cs index 0dbe82d4..66bd63dd 100644 --- a/src/clis/vz/commands/face_command.cs +++ b/src/clis/vz/commands/face_command.cs @@ -21,9 +21,8 @@ namespace Azure.AI.Details.Common.CLI { public class FaceCommand : Command { - internal FaceCommand(ICommandValues values) + internal FaceCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } diff --git a/src/clis/vz/commands/image_command.cs b/src/clis/vz/commands/image_command.cs index c501cde9..f2353072 100644 --- a/src/clis/vz/commands/image_command.cs +++ b/src/clis/vz/commands/image_command.cs @@ -53,10 +53,9 @@ public override ValueTask GetTokenAsync(TokenRequestContext request public class ImageCommand : Command { - internal ImageCommand(ICommandValues values) + internal ImageCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); - _quiet = _values.GetOrDefault("x.quiet", false); + _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -153,7 +152,7 @@ private ImageAnalyzer CreateImageAnalyzer() // _disposeAfterStop.Add(visionSource); _disposeAfterStop.Add(analyzer); - // _output.EnsureCachePropertyCollection("recognizer", recognizer.Properties); + // _output!.EnsureCachePropertyCollection("recognizer", recognizer.Properties); return analyzer; } @@ -189,10 +188,10 @@ private VisionServiceOptions CreateVisionServiceOptions() _values.AddThrowError("ERROR:", $"Creating VisionServiceOptions; requires one of: key or token."); } - // var stringProperty = values.GetOrDefault("config.string.property", ""); + // var stringProperty = values.GetOrEmpty("config.string.property"); // if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - // var stringProperties = values.GetOrDefault("config.string.properties", ""); + // var stringProperties = values.GetOrEmpty("config.string.properties"); // if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); return serviceOptions; @@ -233,7 +232,7 @@ private VisionSource CreateVisionSource() private ImageAnalysisOptions CreateImageAnalysisOptions() { - var featuresRequested = _values.GetOrDefault("vision.image.visual.features", ""); + var featuresRequested = _values.GetOrEmpty("vision.image.visual.features"); var features = string.IsNullOrEmpty(featuresRequested) ? GetDefaultImageAnalysisFeatures() : GetImageAnalysisFeatures(featuresRequested); @@ -276,11 +275,11 @@ private ImageAnalysisFeature GetImageAnalysisFeatures(string requested) return features; } - private void Analyzed(object sender, ImageAnalysisEventArgs e) + private void Analyzed(object? sender, ImageAnalysisEventArgs e) { - _display.DisplayAnalyzed(e); - // _output.Recognized(e); - _lock.ExitReaderLockOnce(ref _expectAnalyzed); + _display!.DisplayAnalyzed(e); + // _output!.Recognized(e); + _lock!.ExitReaderLockOnce(ref _expectAnalyzed); } private void CheckVisionInput() @@ -408,7 +407,7 @@ public void EnsureStartLogFile() var log = _values["diagnostics.config.log.file"]; if (!string.IsNullOrEmpty(log)) { - var id = _values.GetOrDefault("vision.input.id", ""); + var id = _values.GetOrEmpty("vision.input.id"); if (log.Contains("{id}")) log = log.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -417,7 +416,7 @@ public void EnsureStartLogFile() var time = DateTime.Now.ToFileTime().ToString(); if (log.Contains("{time}")) log = log.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (log.Contains("{run.time}")) log = log.Replace("{run.time}", runTime); log = FileHelpers.GetOutputDataFileName(log, _values); @@ -443,15 +442,15 @@ private void StartCommand() _display = new DisplayHelper(_values); // _output = new OutputHelper(_values); - // _output.StartOutput(); + // _output!.StartOutput(); // var id = _values["vision.input.id"]; - // _output.EnsureOutputAll("vision.input.id", id); - // _output.EnsureOutputEach("vision.input.id", id); - // _output.EnsureCacheProperty("vision.input.id", id); + // _output!.EnsureOutputAll("vision.input.id", id); + // _output!.EnsureOutputEach("vision.input.id", id); + // _output!.EnsureCacheProperty("vision.input.id", id); // var file = _values["vision.input.file"]; - // _output.EnsureCacheProperty("vision.input.file", file); + // _output!.EnsureCacheProperty("vision.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -463,13 +462,13 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); // This shouldn't really be here, but since there is no session stopped event it hast to be here _stopEvent.Set(); - // _output.CheckOutput(); - // _output.StopOutput(); + // _output!.CheckOutput(); + // _output!.StopOutput(); } private bool _quiet = false; @@ -479,12 +478,12 @@ private void StopCommand() // private bool _connect = false; // private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectAnalyzed = 0; // private int _expectSessionStopped = 0; // private int _expectDisconnected = 0; - // OutputHelper _output = null; - DisplayHelper _display = null; + // OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/clis/vz/commands/person_command.cs b/src/clis/vz/commands/person_command.cs index 4c5a19fd..7859e0fe 100644 --- a/src/clis/vz/commands/person_command.cs +++ b/src/clis/vz/commands/person_command.cs @@ -21,9 +21,8 @@ namespace Azure.AI.Details.Common.CLI { public class PersonCommand : Command { - internal PersonCommand(ICommandValues values) + internal PersonCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -100,7 +99,7 @@ private void DoCreatePersonGroup() GetGroupId(out string kind, out string id, false); if (string.IsNullOrEmpty(id)) id = Guid.NewGuid().ToString(); - var name = _values.GetOrDefault("person.group.name", ""); + var name = _values.GetOrEmpty("person.group.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -192,7 +191,7 @@ private void DoCreatePerson() { GetGroupId(out string kind, out string id); - var name = _values.GetOrDefault("person.name", ""); + var name = _values.GetOrEmpty("person.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -252,7 +251,7 @@ private void DoAddPersonFace() var message = $"Adding {kind} person face ('{id}') ..."; if (!_quiet) Console.WriteLine(message); - var file = _values.GetOrDefault("vision.input.file", ""); + var file = _values.GetOrEmpty("vision.input.file"); var existing = FileHelpers.FindFileInDataPath(file, _values); var query = GetAddPersonFaceQueryString(file, existing); @@ -320,21 +319,21 @@ private void GetGroupPersonAndFaceIds(out string kind, out string groupId, out s private void GetIds(out string kind, out string groupId, out string personId, out string id, bool groupIdRequired, bool personIdRequired, bool faceIdRequired) { kind = _values.GetOrDefault("person.group.kind", "large"); - groupId = _values.GetOrDefault("person.group.id", ""); + groupId = _values.GetOrEmpty("person.group.id"); if (string.IsNullOrEmpty(groupId) && groupIdRequired) { _values.AddThrowError( "WARNING:", $"Group id not specified!", "", "USE:", $"{Program.Name} {_values.GetCommandForDisplay()} --group id ID [...]"); } - personId = _values.GetOrDefault("person.id", ""); + personId = _values.GetOrEmpty("person.id"); if (string.IsNullOrEmpty(personId) && personIdRequired) { _values.AddThrowError( "WARNING:", $"Person id not specified!", "", "USE:", $"{Program.Name} {_values.GetCommandForDisplay()} --person id ID [...]"); } - id = _values.GetOrDefault("person.face.id", ""); + id = _values.GetOrEmpty("person.face.id"); if (string.IsNullOrEmpty(id) && faceIdRequired) { _values.AddThrowError( @@ -410,8 +409,8 @@ private void GetListParameters(string kind, out string path, out string message, "SEE:", $"{Program.Name} help person"); } - var top = _values.GetOrDefault("person.top", ""); - var skip = _values.GetOrDefault("person.skip", ""); + var top = _values.GetOrEmpty("person.top"); + var skip = _values.GetOrEmpty("person.skip"); query = ""; if (!string.IsNullOrEmpty(skip)) query += $"&skip={skip}"; @@ -493,10 +492,10 @@ private string GetUpdatePersonFacePostJson(string groupKind) return $"{{{sb.ToString().Trim(',', ' ')}}}"; } - private HttpWebRequest CreateWebRequest(string method, string path, string id = null, string query = null, string contentType = null) + private HttpWebRequest CreateWebRequest(string method, string path, string? id = null, string? query = null, string? contentType = null) { - var key = _values.GetOrDefault("service.config.key", ""); - var region = _values.GetOrDefault("service.config.region", ""); + var key = _values.GetOrEmpty("service.config.key"); + var region = _values.GetOrEmpty("service.config.region"); var timeout = _values.GetOrDefault("person.wait.timeout", 100000); if (string.IsNullOrEmpty(region) || string.IsNullOrEmpty(key)) @@ -524,7 +523,7 @@ private HttpWebRequest CreateWebRequest(string method, string path, string id = return request; } - private string GetFaceApiUrl(string region, string path, string id = null, string query = null) + private string GetFaceApiUrl(string region, string path, string? id = null, string? query = null) { if (path.StartsWith("http")) return path; @@ -543,7 +542,7 @@ private string GetFaceApiUrl(string region, string path, string id = null, strin private string CheckWriteOutputRequest(HttpWebRequest request, string payload = null, bool append = false) { - var output = _values.GetOrDefault("person.output.request.file", ""); + var output = _values.GetOrEmpty("person.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); @@ -554,7 +553,7 @@ private string CheckWriteOutputRequest(HttpWebRequest request, string payload = private byte[] CheckWriteOutputRequest(HttpWebRequest request, byte[] payload) { - var output = _values.GetOrDefault("person.output.request.file", ""); + var output = _values.GetOrEmpty("person.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); diff --git a/src/common/Program.cs b/src/common/Program.cs index 1b43d448..582c2deb 100644 --- a/src/common/Program.cs +++ b/src/common/Program.cs @@ -192,7 +192,7 @@ public static string GetVersionFromAssembly() } } - return version; + return version ?? string.Empty; } private static void DisplayCommandHelp(INamedValueTokens tokens, INamedValues values) @@ -259,7 +259,7 @@ private static void DisplayParsedValues(INamedValues values) if (key == "display.help") continue; if (key == "display.version") continue; - var value = values[key]; + var value = values[key]!; var obfuscateValue = key.EndsWith(passwordPostfix) || (key.Length > subKeyPostfix.Length && key.EndsWith(subKeyPostfix) && ((value.Length == validSubKeyLength && Guid.TryParse(value, out Guid result)) || @@ -271,7 +271,7 @@ private static void DisplayParsedValues(INamedValues values) var lines = value.Split(delimeters.ToArray()).Where(x => x.Trim().Length > 0); int chars = value.Length - maxValueLength; - value = lines.FirstOrDefault(); + value = lines.FirstOrDefault() ?? string.Empty; var truncated = ""; if (lines.Count() > 1) @@ -321,7 +321,7 @@ private static bool DisplayErrorValue(INamedValues values) return false; } - private static int DisplayParseErrorHelpOrException(INamedValueTokens tokens, ICommandValues values, Exception ex, bool displayBanner) + private static int DisplayParseErrorHelpOrException(INamedValueTokens tokens, ICommandValues values, Exception? ex, bool displayBanner) { if (values.Contains("error")) { @@ -394,7 +394,7 @@ private static void TryCatchErrorOrException(ICommandValues values, Action actio private static bool RunCommand(ICommandValues values) { - string errorInfo = null; + string? errorInfo = null; var outcome = Outcome.Unknown; try @@ -428,7 +428,7 @@ private static bool RunCommand(ICommandValues values) { _data?.Telemetry?.LogEvent(new CommandTelemetryEvent() { - Type = values.GetCommand("unknown"), + Type = values.GetCommand("unknown")!, Outcome = outcome, ErrorInfo = errorInfo }); @@ -437,49 +437,49 @@ private static bool RunCommand(ICommandValues values) return outcome == Outcome.Success; } - private static IProgramData _data; + private static IProgramData? _data; - public static string Name => _data?.Name; + public static string Name => _data?.Name!; - public static string DisplayName => _data?.DisplayName; + public static string DisplayName => _data?.DisplayName!; - public static string WarningBanner => _data?.WarningBanner; + public static string WarningBanner => _data?.WarningBanner!; - public static string TelemetryUserAgent => _data?.TelemetryUserAgent; + public static string TelemetryUserAgent => _data?.TelemetryUserAgent!; - public static string Exe => _data?.Exe; + public static string Exe => _data?.Exe!; - public static string Dll => _data?.Dll; + public static string Dll => _data?.Dll!; - public static Type ResourceAssemblyType => _data?.ResourceAssemblyType; + public static Type ResourceAssemblyType => _data?.ResourceAssemblyType!; - public static Assembly ResourceAssembly => _data?.ResourceAssemblyType.Assembly; + public static Assembly ResourceAssembly => _data?.ResourceAssemblyType.Assembly!; - public static Type BindingAssemblySdkType => _data?.BindingAssemblySdkType; + public static Type BindingAssemblySdkType => _data?.BindingAssemblySdkType!; - public static string SERVICE_RESOURCE_DISPLAY_NAME_ALL_CAPS => _data?.SERVICE_RESOURCE_DISPLAY_NAME_ALL_CAPS; + public static string SERVICE_RESOURCE_DISPLAY_NAME_ALL_CAPS => _data?.SERVICE_RESOURCE_DISPLAY_NAME_ALL_CAPS!; - public static string CognitiveServiceResourceKind => _data?.CognitiveServiceResourceKind; + public static string CognitiveServiceResourceKind => _data?.CognitiveServiceResourceKind!; - public static string CognitiveServiceResourceSku => _data?.CognitiveServiceResourceSku; + public static string CognitiveServiceResourceSku => _data?.CognitiveServiceResourceSku!; public static bool InitConfigsEndpoint => _data != null && _data.InitConfigsEndpoint; public static bool InitConfigsSubscription => _data != null && _data.InitConfigsSubscription; - public static string HelpCommandTokens => _data?.HelpCommandTokens; + public static string HelpCommandTokens => _data?.HelpCommandTokens!; - public static string ConfigScopeTokens => _data?.ConfigScopeTokens; + public static string ConfigScopeTokens => _data?.ConfigScopeTokens!; - public static string[] ZipIncludes => _data?.ZipIncludes; + public static string[] ZipIncludes => _data?.ZipIncludes!; public static bool DispatchRunCommand(ICommandValues values) => _data != null && _data.DispatchRunCommand(values); public static bool DispatchParseCommand(INamedValueTokens tokens, ICommandValues values) => _data != null && _data.DispatchParseCommand(tokens, values); public static bool DispatchParseCommandValues(INamedValueTokens tokens, ICommandValues values) => _data != null && _data.DispatchParseCommandValues(tokens, values); public static bool DisplayKnownErrors(ICommandValues values, Exception ex) => _data != null && _data.DisplayKnownErrors(values, ex); - public static IEventLoggerHelpers EventLoggerHelpers => _data?.EventLoggerHelpers; + public static IEventLoggerHelpers EventLoggerHelpers => _data?.EventLoggerHelpers!; - public static ITelemetry Telemetry => _data.Telemetry; + public static ITelemetry Telemetry => _data?.Telemetry!; } } diff --git a/src/common/Telemetry/Events/InitTelemetryEvent.cs b/src/common/Telemetry/Events/InitTelemetryEvent.cs index 27f169b6..257d82ff 100644 --- a/src/common/Telemetry/Events/InitTelemetryEvent.cs +++ b/src/common/Telemetry/Events/InitTelemetryEvent.cs @@ -88,13 +88,13 @@ public InitTelemetryEvent(InitStage stage) /// A unique identifier for this particular run of the init command. This can be used to uniquely identify /// a single sequence of events /// - public string RunId { get; init; } + public string? RunId { get; init; } /// /// The type of init run we are doing. Due to subtle differences in the various options, there are currently /// 3 kinds: new, existing, standalone_{resType} /// - public string RunType { get; init; } + public string? RunType { get; init; } /// /// The outcome of this step @@ -104,7 +104,7 @@ public InitTelemetryEvent(InitStage stage) /// /// (Optional) Some additional information about what was selected (e.g. new, existing, skipped) /// - public string Selected { get; init; } + public string? Selected { get; init; } /// /// How long the user spent in that particular stage @@ -114,6 +114,6 @@ public InitTelemetryEvent(InitStage stage) /// /// (Optional) Any error information encountered that lead to a failed outcome /// - public string Error { get; init; } + public string? Error { get; init; } } } diff --git a/src/common/Telemetry/ITelemetry.cs b/src/common/Telemetry/ITelemetry.cs index 80497b90..5e54fba7 100644 --- a/src/common/Telemetry/ITelemetry.cs +++ b/src/common/Telemetry/ITelemetry.cs @@ -41,7 +41,7 @@ public static class TelemetryExtensions /// How long the function or work took /// The telemetry event to raise, or null to not raise an event public delegate ITelemetryEvent CreateTelemetryEvent( - Outcome outcome, Exception exception, TimeSpan duration); + Outcome outcome, Exception? exception, TimeSpan duration); /// /// Creates a telemetry event @@ -53,7 +53,7 @@ public delegate ITelemetryEvent CreateTelemetryEvent( /// How long the function or work took /// The telemetry event to raise, or null to not raise an event public delegate ITelemetryEvent CreateTelemetryEvent( - Outcome outcome, TResult result, Exception exception, TimeSpan duration); + Outcome outcome, TResult? result, Exception? exception, TimeSpan duration); #endregion @@ -147,8 +147,8 @@ public static async Task WrapAsync( CreateTelemetryEvent createTelemetryEvent) { var outcome = Outcome.Unknown; - TResult res = default; - Exception exception = null; + TResult? res = default; + Exception? exception = null; var stopwatch = Stopwatch.StartNew(); try @@ -257,8 +257,8 @@ public static (Outcome, TResult) WrapResult( CreateTelemetryEvent createTelemetryEvent) { var outcome = Outcome.Unknown; - TResult res = default; - Exception exception = null; + TResult? res = default; + Exception? exception = null; var stopwatch = Stopwatch.StartNew(); try @@ -284,7 +284,7 @@ public static (Outcome, TResult) WrapResult( #region helper methods private static CreateTelemetryEvent Wrap(CreateTelemetryEvent creator) => - (Outcome outcome, TResult _, Exception ex, TimeSpan duration) => creator(outcome, ex, duration); + (Outcome outcome, TResult? _, Exception? ex, TimeSpan duration) => creator(outcome, ex, duration); private static Exception FlattenException(Exception ex) { diff --git a/src/common/common.csproj b/src/common/common.csproj index ea206fe9..8542ed1e 100644 --- a/src/common/common.csproj +++ b/src/common/common.csproj @@ -5,6 +5,7 @@ enable Azure.AI.CLI.Common Azure.AI.Details.Common.CLI + enable diff --git a/src/common/details/ai_python_generative_sdk/AiSdkConsoleGui_PickOrCreateAiHubResource.cs b/src/common/details/ai_python_generative_sdk/AiSdkConsoleGui_PickOrCreateAiHubResource.cs index 7aae72c3..f80abcc7 100644 --- a/src/common/details/ai_python_generative_sdk/AiSdkConsoleGui_PickOrCreateAiHubResource.cs +++ b/src/common/details/ai_python_generative_sdk/AiSdkConsoleGui_PickOrCreateAiHubResource.cs @@ -80,9 +80,9 @@ public static async Task CreateAiHubResource(ICommandValues v var byoServices = allowCreate && picked == 1; if (byoServices) { - var regionFilter = values.GetOrDefault("init.service.resource.region.name", ""); - var groupFilter = values.GetOrDefault("init.service.resource.group.name", ""); - var resourceFilter = values.GetOrDefault("init.service.cognitiveservices.resource.name", ""); + var regionFilter = values.GetOrEmpty("init.service.resource.region.name"); + var groupFilter = values.GetOrEmpty("init.service.resource.group.name"); + var resourceFilter = values.GetOrEmpty("init.service.cognitiveservices.resource.name"); var kind = values.GetOrDefault("init.service.cognitiveservices.resource.kind", "OpenAI;AIServices"); var sku = values.GetOrDefault("init.service.cognitiveservices.resource.sku", Program.CognitiveServiceResourceSku); var yes = values.GetOrDefault("init.service.cognitiveservices.terms.agree", false); @@ -110,13 +110,13 @@ public static async Task CreateAiHubResource(ICommandValues v private static async Task TryCreateAiHubResourceInteractive(ICommandValues values, string subscription) { - var locationName = values.GetOrDefault("service.resource.region.name", ""); + var locationName = values.GetOrEmpty("service.resource.region.name"); var groupName = ResourceGroupNameToken.Data().GetOrDefault(values); var displayName = ResourceDisplayNameToken.Data().GetOrDefault(values); var description = ResourceDescriptionToken.Data().GetOrDefault(values); - var openAiResourceId = values.GetOrDefault("service.openai.resource.id", ""); - var openAiResourceKind = values.GetOrDefault("service.openai.resource.kind", ""); + var openAiResourceId = values.GetOrEmpty("service.openai.resource.id"); + var openAiResourceKind = values.GetOrEmpty("service.openai.resource.kind"); var smartName = ResourceNameToken.Data().GetOrDefault(values); var smartNameKind = smartName != null && smartName.Contains("openai") ? "openai" : "oai"; diff --git a/src/common/details/commands/command.cs b/src/common/details/commands/command.cs index e96fce5b..0186488a 100644 --- a/src/common/details/commands/command.cs +++ b/src/common/details/commands/command.cs @@ -44,7 +44,7 @@ public static bool DispatchRunCommand(ICommandValues values) return DispatchRunCommand(values, queue, true, true); } - public static bool DispatchRunCommand(ICommandValues values, Queue queue, bool expandOk, bool parallelOk) + public static bool DispatchRunCommand(ICommandValues values, Queue? queue, bool expandOk, bool parallelOk) { var command = values.GetCommand(); @@ -77,7 +77,7 @@ public static bool ZipCommand(ICommandValues values, string zipAsFile) if (!zipAsFile.EndsWith(".zip")) zipAsFile = zipAsFile + ".zip"; - var tempDirectory = PathHelpers.Combine(Path.GetTempPath(), zipAsFile + DateTime.Now.ToFileTime().ToString() + ".temp"); + var tempDirectory = PathHelpers.Combine(Path.GetTempPath(), zipAsFile + DateTime.Now.ToFileTime().ToString() + ".temp")!; Directory.CreateDirectory(tempDirectory); ZipCommand(values, zipAsFile, tempDirectory, verbose); @@ -94,7 +94,7 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - var zipTarget = values.GetOrDefault("x.command.zip.target", ""); + var zipTarget = values.GetOrEmpty("x.command.zip.target"); var targetWebJob = zipTarget.ToLower() == "webjob"; // run.cmd or run.sh @@ -104,7 +104,7 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t var command = values.GetCommand(); var commandJob = "./" + command + ".job"; - var runScriptPath = PathHelpers.Combine(tempDirectory, runScript); + var runScriptPath = PathHelpers.Combine(tempDirectory, runScript)!; if (targetWebJob) { @@ -125,7 +125,7 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t if (verbose) Console.WriteLine($" Saving {settingsPath}... "); var settingsJson = "{ \"is_in_place\": true }"; - settingsPath = PathHelpers.Combine(tempDirectory, "settings.job"); + settingsPath = PathHelpers.Combine(tempDirectory, "settings.job")!; FileHelpers.WriteAllText(settingsPath, settingsJson, Encoding.Default); } @@ -133,7 +133,7 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t var files = values.SaveAs(commandJob).Split(';'); foreach (var file in files) { - FileHelpers.CopyFile(".", file, tempDirectory, null, verbose); + FileHelpers.TryCopyFile(".", file, tempDirectory, null, verbose); File.Delete(file); } @@ -141,33 +141,33 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t var sourcePath = AppContext.BaseDirectory; var programExe = OperatingSystem.IsWindows() ? Program.Exe : Program.Exe.Replace(".exe", ""); - FileHelpers.CopyFile(sourcePath, programExe, tempDirectory, null, verbose); + FileHelpers.TryCopyFile(sourcePath, programExe, tempDirectory, null, verbose); #if NETCOREAPP - FileHelpers.CopyFile(sourcePath, Program.Name, tempDirectory, null, verbose); - FileHelpers.CopyFile(sourcePath, Program.Dll, tempDirectory, null, verbose); - FileHelpers.CopyFile(sourcePath, "runtimeconfig.json", tempDirectory, null, verbose); - FileHelpers.CopyFile(sourcePath, $"{Program.Name}.runtimeconfig.json", tempDirectory, null, verbose); + FileHelpers.TryCopyFile(sourcePath, Program.Name, tempDirectory, null, verbose); + FileHelpers.TryCopyFile(sourcePath, Program.Dll, tempDirectory, null, verbose); + FileHelpers.TryCopyFile(sourcePath, "runtimeconfig.json", tempDirectory, null, verbose); + FileHelpers.TryCopyFile(sourcePath, $"{Program.Name}.runtimeconfig.json", tempDirectory, null, verbose); #endif var bindingAssembly = FileHelpers.GetAssemblyFileInfo(Program.BindingAssemblySdkType); - sourcePath = bindingAssembly.DirectoryName; - FileHelpers.CopyFile(sourcePath, bindingAssembly.Name, tempDirectory, null, verbose); + sourcePath = bindingAssembly.DirectoryName!; + FileHelpers.TryCopyFile(sourcePath, bindingAssembly.Name, tempDirectory, null, verbose); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { string[] locations = { "", "runtimes/win-x64/native/", "../runtimes/win-x64/native/" }; - FileHelpers.CopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, null, null, verbose); + FileHelpers.TryCopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, null, null, verbose); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { string[] locations = { "", "runtimes/linux-x64/native/", "../../runtimes/linux-x64/native/" }; - FileHelpers.CopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, "lib", ".so", verbose); + FileHelpers.TryCopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, "lib", ".so", verbose); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { string[] locations = { "", "runtimes/osx-x64/native/", "../../runtimes/osx-x64/native/" }; - FileHelpers.CopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, "lib", ".dylib", verbose); + FileHelpers.TryCopyFiles(PathHelpers.Combine(sourcePath, locations), Program.ZipIncludes, tempDirectory, "lib", ".dylib", verbose); } // Dependent type assemblies (Linq Async, System.Interactive.Async and JMESPath) @@ -176,7 +176,7 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t foreach (var t in types) { var fi = FileHelpers.GetAssemblyFileInfo(t); - FileHelpers.CopyFile(fi.DirectoryName, fi.Name, tempDirectory, null, verbose); + FileHelpers.TryCopyFile(fi.DirectoryName!, fi.Name, tempDirectory, null, verbose); } File.Delete(zipAsFile); @@ -188,7 +188,13 @@ private static void ZipCommand(ICommandValues values, string zipAsFile, string t public class Command { - public static bool RunCommand(ICommandValues values, Queue queue, bool expandOk = true, bool parallelOk = true) + public Command(ICommandValues values) + { + _values = values; + _values.ReplaceValues(); + } + + public static bool RunCommand(ICommandValues values, Queue? queue, bool expandOk = true, bool parallelOk = true) { if (expandOk) return CheckExpandRunCommand(values, queue, expandOk, parallelOk); if (parallelOk) return CheckParallelRunCommand(values, queue, expandOk, ref parallelOk); @@ -196,30 +202,30 @@ public static bool RunCommand(ICommandValues values, Queue queue return queue != null && CheckExpectedRunInProcAsync(values, queue).Result; } - protected static bool CheckExpandRunCommand(ICommandValues values, Queue queue, bool expandOk, bool parallelOk) + protected static bool CheckExpandRunCommand(ICommandValues values, Queue? queue, bool expandOk, bool parallelOk) { bool passed = false; - var fileValueName = values.GetOrDefault("x.command.expand.file.name", ""); - var files = values.GetOrDefault($"{fileValueName}s", ""); + var fileValueName = values.GetOrEmpty("x.command.expand.file.name"); + var files = values.GetOrEmpty($"{fileValueName}s"); var forEachCount = values["foreach.count"]; var repeat = values["x.command.repeat"]; if (!string.IsNullOrEmpty(files)) { - BlockValues(values, queue, $"{fileValueName}s"); - passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueForEachFile(queue, fileValueName, files), expandOk, parallelOk); + BlockValues(values, queue!, $"{fileValueName}s"); + passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueForEachFile(queue!, fileValueName, files), expandOk, parallelOk); } else if (!string.IsNullOrEmpty(forEachCount)) { - BlockValues(values, queue, "foreach.count"); - passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueForEachTsv(values, queue, forEachCount), expandOk, parallelOk); + BlockValues(values, queue!, "foreach.count"); + passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueForEachTsv(values, queue!, forEachCount), expandOk, parallelOk); } else if (!string.IsNullOrEmpty(repeat)) { - BlockValues(values, queue, "x.command.repeat"); - passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueFromRepeatCount(queue, repeat), expandOk, parallelOk); + BlockValues(values, queue!, "x.command.repeat"); + passed = CommandRunDispatcher.DispatchRunCommand(values, ExpandQueueFromRepeatCount(queue!, repeat), expandOk, parallelOk); } else { @@ -289,7 +295,7 @@ protected static Queue ExpandQueueForEachTsv(INamedValues tsvOpt { var forEachTsvFile = $"foreach.{i}.tsv.file"; - var forEachItems = new Queue(tsvOptions.GetOrDefault(forEachTsvFile, "").Split('\n', '\r').Where(x => x.Trim().Length > 0)); + var forEachItems = new Queue(tsvOptions.GetOrEmpty(forEachTsvFile).Split('\n', '\r').Where(x => x.Trim().Length > 0)); BlockValues(tsvOptions, queue, forEachTsvFile); var hasHeader = tsvOptions.GetOrDefault(forEachTsvFile + ".has.header", true); @@ -299,7 +305,7 @@ protected static Queue ExpandQueueForEachTsv(INamedValues tsvOpt BlockValues(tsvOptions, queue, forEachTsvFile + ".skip.header"); var defaultColumns = hasHeader ? forEachItems.Dequeue() : "audio.input.id\taudio.input.file"; - var tsvColumns = tsvOptions.GetOrDefault(forEachTsvFile + ".columns", defaultColumns); + var tsvColumns = tsvOptions.GetOrDefault(forEachTsvFile + ".columns", defaultColumns)!; BlockValues(tsvOptions, queue, forEachTsvFile + ".columns"); if (forEachItems.Count() >= 1) @@ -337,7 +343,7 @@ protected static ICommandValues CombineValuesWithTsvRow(ICommandValues allRows, var names = new List(thisRow.Names); foreach (var name in names) { - var value = thisRow[name]; + var value = thisRow[name]!; if (value.StartsWith("@@")) { var newValue = FileHelpers.ExpandAtFileValue(value.Substring(1), thisRow); @@ -371,7 +377,7 @@ protected static ICommandValues CombineValuesWithNameValue(ICommandValues baseVa return values; } - protected static bool CheckParallelRunCommand(ICommandValues values, Queue queue, bool expandOk, ref bool parallelOk) + protected static bool CheckParallelRunCommand(ICommandValues values, Queue? queue, bool expandOk, ref bool parallelOk) { bool passed; var processCount = values.GetOrDefault("x.command.parallel.process.count", 0); @@ -380,16 +386,16 @@ protected static bool CheckParallelRunCommand(ICommandValues values, Queue 0) { var rampEvery = values.GetOrDefault("x.command.parallel.ramp.threads.every", 0); - BlockValues(values, queue, "x.command.parallel.ramp.processes.every"); - BlockValues(values, queue, "x.command.parallel.process.count"); - passed = CheckExpectedRunOutOfProcAsync(values, queue, processCount, rampEvery).Result; + BlockValues(values, queue!, "x.command.parallel.ramp.processes.every"); + BlockValues(values, queue!, "x.command.parallel.process.count"); + passed = CheckExpectedRunOutOfProcAsync(values, queue!, processCount, rampEvery).Result; } else if (threadCount > 0) { var rampEvery = values.GetOrDefault("x.command.parallel.ramp.threads.every", 0); - BlockValues(values, queue, "x.command.parallel.ramp.threads.every"); - BlockValues(values, queue, "x.command.parallel.thread.count"); - passed = CheckExpectedRunOnThreadsAsync(values, queue, threadCount, rampEvery).Result; + BlockValues(values, queue!, "x.command.parallel.ramp.threads.every"); + BlockValues(values, queue!, "x.command.parallel.thread.count"); + passed = CheckExpectedRunOnThreadsAsync(values, queue!, threadCount, rampEvery).Result; } else { @@ -408,9 +414,13 @@ protected void CheckPath() protected string DownloadInputFile(string file, string fileValueName, string fileValueDisplayName) { var downloaded = HttpHelpers.DownloadFileWithRetry(file); - if (FileHelpers.FileExistsInDataPath(downloaded, _values)) + if (downloaded == null) + { + _values.AddThrowError("ERROR:", $"Cannot download {fileValueDisplayName} file: \"{file}\""); + } + else if (FileHelpers.FileExistsInDataPath(downloaded!, _values)) { - file = downloaded; + file = downloaded!; _values.Reset(fileValueName, file); _delete.Add(file); } @@ -439,7 +449,7 @@ protected string GetIdFromInputUrl(string url, string idValueName) protected string ReplaceFileNameValues(string fileName, string idValueName) { - var id = _values.GetOrDefault(idValueName, ""); + var id = _values.GetOrEmpty(idValueName); if (fileName.Contains("{id}")) fileName = fileName.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -448,7 +458,7 @@ protected string ReplaceFileNameValues(string fileName, string idValueName) var time = DateTime.Now.ToFileTime().ToString(); if (fileName.Contains("{time}")) fileName = fileName.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (fileName.Contains("{run.time}")) fileName = fileName.Replace("{run.time}", runTime); return fileName.ReplaceValues(_values); @@ -464,7 +474,7 @@ protected void DisposeAfterStop() _disposeAfterStop.Reverse(); // objects should be disposed in reverse order created foreach (var item in _disposeAfterStop) { - item.Dispose(); + item?.Dispose(); } } } @@ -488,11 +498,11 @@ private static bool ShouldCheckExpected(string expected, string notExpected, out { expectedItems = !string.IsNullOrEmpty(expected) ? expected.Split(new char[] { ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) - : null; + : Enumerable.Empty(); notExpectedItems = !string.IsNullOrEmpty(notExpected) ? notExpected.Split(new char[] { ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) - : null; - return expectedItems != null || notExpectedItems != null; + : Enumerable.Empty(); + return expectedItems.Count() + notExpectedItems.Count() > 0; } private static async Task CheckExpectedLogOutputAsync(IEnumerable expected, IEnumerable notExpected, bool autoExpect, string autoExpectLogFilter, AutoResetEvent signalStop) @@ -523,13 +533,13 @@ private static async Task CheckExpectedLogOutputAsync(IEnumerable private static async Task CheckExpectedOutputAsync(ICommandValues values, Queue queue, Func func) { - var expected = values.GetOrDefault("x.command.output.expect", ""); - var notExpected = values.GetOrDefault("x.command.output.not.expect", ""); + var expected = values.GetOrEmpty("x.command.output.expect"); + var notExpected = values.GetOrEmpty("x.command.output.not.expect"); var autoExpect = values.GetOrDefault("x.command.output.auto.expect", false); - var expectedLog = values.GetOrDefault("x.command.diagnostics.log.expect", ""); - var notExpectedLog = values.GetOrDefault("x.command.diagnostics.log.not.expect", ""); + var expectedLog = values.GetOrEmpty("x.command.diagnostics.log.expect"); + var notExpectedLog = values.GetOrEmpty("x.command.diagnostics.log.not.expect"); var autoExpectLog = values.GetOrDefault("x.command.diagnostics.log.auto.expect", false); - var autoExpectLogFilter = values.GetOrDefault("x.command.diagnostics.log.auto.expect.filter", ""); + var autoExpectLogFilter = values.GetOrEmpty("x.command.diagnostics.log.auto.expect.filter"); var ignoreCheckFailures = values.GetOrDefault("x.command.output.ignore.check.failures", false); BlockValues(values, queue, "x.command.output.expect"); @@ -606,7 +616,7 @@ private static bool RunCommandsOutOfProc(Queue queue, int maxPro var start = new ProcessStartInfo(Program.Exe, $"{values.GetCommand()} --nodefaults @{fileName}"); start.UseShellExecute = false; - var process = Process.Start(start); + var process = Process.Start(start)!; processes.Add(fileNames, process); WaitForProcesses(rampStarted, rampDuration, maxProcesses, processes, ref passed); @@ -739,7 +749,7 @@ private static IEnumerable SplitLines(string files) protected ManualResetEvent _stopEvent = new ManualResetEvent(false); protected ManualResetEvent _canceledEvent = new ManualResetEvent(false); - protected List _disposeAfterStop = new List(); + protected List _disposeAfterStop = new List(); protected List _delete = new List(); } } diff --git a/src/common/details/commands/command_values.cs b/src/common/details/commands/command_values.cs index bca1f29d..61d9e885 100644 --- a/src/common/details/commands/command_values.cs +++ b/src/common/details/commands/command_values.cs @@ -17,13 +17,13 @@ public interface ICommandValues : INamedValues public class CommandValues : ICommandValues, INamedValues { - public CommandValues(INamedValues defaults = null) + public CommandValues(INamedValues? defaults = null) { _defaults = defaults == null ? _overrides : defaults; _values = new NamedValues(); } - public void Add(string name, string value) + public void Add(string name, string? value) { _values.Add(name, value); } @@ -38,7 +38,7 @@ public bool Contains(string name, bool checkDefault = true) return !blockValue && (containsValue || (checkDefault && _defaults.Contains(name, true))); } - public string Get(string name, bool checkDefault = true) + public string? Get(string name, bool checkDefault = true) { var containsOverride = _overrides.Contains(name, false); if (containsOverride) return _overrides.Get(name, false); @@ -53,7 +53,7 @@ public string Get(string name, bool checkDefault = true) return checkDefault ? _defaults.Get(name, true) : value; } - public void Reset(string name, string value = null) + public void Reset(string name, string? value = null) { _values.Reset(name); if (value != null) @@ -62,7 +62,7 @@ public void Reset(string name, string value = null) } } - public string this[string name] + public string? this[string name] { get { diff --git a/src/common/details/commands/config_command.cs b/src/common/details/commands/config_command.cs index 7334e1f1..864f43cb 100644 --- a/src/common/details/commands/config_command.cs +++ b/src/common/details/commands/config_command.cs @@ -16,6 +16,10 @@ namespace Azure.AI.Details.Common.CLI { public class ConfigCommand : Command { + internal ConfigCommand(ICommandValues values) : base(values) + { + } + internal static bool RunCommand(ICommandValues values) { var atFile = values.GetOrDefault("x.config.command.at.file", null); @@ -37,7 +41,7 @@ internal static bool RunCommand(ICommandValues values) return DoAtFile($"{Program.Name}.defaults", values); } - private static bool DoSetValue(string setValue, string fileName, ICommandValues values) + private static bool DoSetValue(string setValue, string? fileName, ICommandValues values) { if (!string.IsNullOrEmpty(fileName)) { @@ -67,7 +71,7 @@ private static bool DoSetValue(string setValue, string fileName, ICommandValues return false; } - private static bool DoAddValue(string addValue, string fileName, ICommandValues values) + private static bool DoAddValue(string addValue, string? fileName, ICommandValues values) { if (!string.IsNullOrEmpty(fileName)) { @@ -97,9 +101,9 @@ private static bool DoAddValue(string addValue, string fileName, ICommandValues return false; } - private static bool DoShowValue(string path, string verbPhrase, ICommandValues values = null) + private static bool DoShowValue(string path, string verbPhrase, ICommandValues? values = null) { - var quiet = values.GetOrDefault("x.quiet", false); + var quiet = values != null && values.GetOrDefault("x.quiet", false)!; if (!quiet) { @@ -159,7 +163,7 @@ private static bool DoFindFiles(string file, ICommandValues values) return true; } - private static bool DoClearValue(string clearValue, string atFile, ICommandValues values) + private static bool DoClearValue(string clearValue, string? atFile, ICommandValues values) { var fileName = !string.IsNullOrEmpty(atFile) ? atFile.TrimStart('@') @@ -201,8 +205,8 @@ private static bool DoClearValue(string clearValue, string atFile, ICommandValue "SEE:", $"{Program.Name} help config"); } - DoShowValue(existing, "deleted from", values); - File.Delete(existing); + DoShowValue(existing!, "deleted from", values); + File.Delete(existing!); return true; } @@ -241,13 +245,13 @@ private static string AdjustOutputFileName(string fileName, ICommandValues value return AdjustOutputFileNameScope(fileName, regionScope, commandScope, values); } - private static string AdjustOutputFileNameScope(string fileName, string region, string command, ICommandValues values) + private static string AdjustOutputFileNameScope(string fileName, string? region, string? command, ICommandValues values) { fileName = AdjustFileNameScope(fileName, region, command); return FileHelpers.GetOutputConfigFileName(fileName, values); } - private static string AdjustFileNameScope(string fileName, string region, string command) + private static string AdjustFileNameScope(string fileName, string? region, string? command) { fileName = fileName.TrimStart('@'); if (!string.IsNullOrEmpty(command)) fileName = $"{command}.{fileName}"; diff --git a/src/common/details/commands/parsers/command_parser.cs b/src/common/details/commands/parsers/command_parser.cs index 90f9d09b..8acb909b 100644 --- a/src/common/details/commands/parsers/command_parser.cs +++ b/src/common/details/commands/parsers/command_parser.cs @@ -71,7 +71,7 @@ public class CommandParser { protected static bool ParseCommandValues(string commandName, IEnumerable parsers, INamedValueTokens tokens, ICommandValues values) { - return commandName != null && values.GetCommand().StartsWith(commandName) && ParseAllCommandValues(parsers, tokens, values); + return commandName != null && values.GetCommand()!.StartsWith(commandName) && ParseAllCommandValues(parsers, tokens, values); } protected static bool ParseCommand(string commandName, IEnumerable parsers, INamedValueTokens tokens, ICommandValues values) @@ -84,7 +84,7 @@ protected static bool ParseCommand(string commandName, IEnumerable commands, IEnumerable partials, INamedValueTokens tokens, ICommandValues values, Func> parsers) { return ParseCommandName(commands, partials, tokens, values) && - ParseCommandDefaults(values.GetCommand(), parsers(values), tokens, values) && + ParseCommandDefaults(values.GetCommand()!, parsers(values), tokens, values) && ParseAllCommandValues(parsers(values), tokens, values); } @@ -219,7 +219,7 @@ protected static bool ParseAllCommandValues(IEnumerable bool parsed = true; while (tokens.PeekNextToken() != null) { - parsed = tokens.PeekNextToken().StartsWith("@") + parsed = tokens.PeekNextToken()!.StartsWith("@") ? ParseAtFileToken(parsers, tokens, values) : ParseNextCommandValue(parsers, tokens, values); @@ -266,9 +266,9 @@ private static bool ExpectsDefaults(string commandName) private static bool ParseAtFileToken(IEnumerable parsers, INamedValueTokens tokens, ICommandValues values) { - if (tokens.PeekNextToken().StartsWith("@")) + if (tokens.PeekNextToken()?.StartsWith("@") ?? false) { - var iniFile = tokens.PeekNextTokenValue(0, values); + var iniFile = tokens.PeekNextTokenValue(0, values)!; if (ParseIniFileLines(iniFile, parsers, values)) { tokens.PopNextToken(); @@ -288,7 +288,7 @@ private static bool ParseIniFileValue(IEnumerable parser var iniFile = values["ini.file"]; values.Reset("ini.file"); - return ParseIniFileLines(iniFile, parsers, values); + return ParseIniFileLines(iniFile!, parsers, values); } private static bool ParseIniFile(string fileName, IEnumerable parsers, INamedValues values) diff --git a/src/common/details/commands/parsers/help_command_parser.cs b/src/common/details/commands/parsers/help_command_parser.cs index aa6f4c53..89ae393d 100644 --- a/src/common/details/commands/parsers/help_command_parser.cs +++ b/src/common/details/commands/parsers/help_command_parser.cs @@ -34,15 +34,15 @@ public static bool ParseCommand(INamedValueTokens tokens, ICommandValues values) public static bool ParseCommandValues(INamedValueTokens tokens, ICommandValues values) { - return ParseCommandValues("help", null, tokens, values); + return ParseCommandValues("help", Enumerable.Empty(), tokens, values); } public static bool DisplayHelp(INamedValueTokens tokens, INamedValues values) { - var topicSearch = values.GetOrDefault("display.help.topic", ""); + var topicSearch = values.GetOrEmpty("display.help.topic"); if (!string.IsNullOrEmpty(topicSearch)) return DoListHelpTopics(topicSearch, values); - var textSearch = values.GetOrDefault("display.help.text", ""); + var textSearch = values.GetOrEmpty("display.help.text"); if (!string.IsNullOrEmpty(textSearch)) return DoFindHelpTopics(textSearch, values); return DoDisplayHelpTopic(values); @@ -71,9 +71,9 @@ private static bool ParseHelpCommandTokens(INamedValueTokens tokens, ICommandVal return true; } - private static string ParseHelpCommandToken(INamedValueTokens tokens, ICommandValues values, ref string token) + private static string ParseHelpCommandToken(INamedValueTokens tokens, ICommandValues values, ref string? token) { - string command = values.GetOrDefault("x.command", ""); + string command = values.GetOrEmpty("x.command"); if (command == "help") command = ""; if (string.IsNullOrEmpty(command) && token != null && IsHelpCommandToken(token)) @@ -99,7 +99,7 @@ private static bool IsHelpCommandToken(string token) return $";{Program.HelpCommandTokens};".Contains($";{token};"); } - private static string ParseHelpCommandOptionToken(INamedValueTokens tokens, ref string token) + private static string ParseHelpCommandOptionToken(INamedValueTokens tokens, ref string? token) { string option = ""; if (token != null && token.StartsWith("--")) @@ -112,7 +112,7 @@ private static string ParseHelpCommandOptionToken(INamedValueTokens tokens, ref return option; } - private static string ParseHelpCommandMoreTokens(INamedValueTokens tokens, ref string token) + private static string ParseHelpCommandMoreTokens(INamedValueTokens tokens, ref string? token) { string more = ""; while (token != null) @@ -206,7 +206,7 @@ private static string TrimHelpTokens(string allTokens) private static bool DoDisplayHelpTopic(INamedValues values) { - var allTokens = values.GetOrDefault("display.help.tokens", ""); + var allTokens = values.GetOrEmpty("display.help.tokens"); if (allTokens == "colors") { ColorHelpers.ShowColorChart(); @@ -218,7 +218,7 @@ private static bool DoDisplayHelpTopic(INamedValues values) var result = path != null ? DisplayHelp(path, values) : DisplayDefaultHelp(); var checkTokensFound = allTokens?.Replace(" ", ".").Replace("--", "").Split('.'); - var foundAllTokens = path == null || checkTokensFound.Count(x => path.Contains(x)) == checkTokensFound.Count(); + var foundAllTokens = path == null || checkTokensFound?.Count(x => path.Contains(x)) == checkTokensFound?.Count(); if (!foundAllTokens) { @@ -373,13 +373,13 @@ private static bool HelpContainsText(string help, string search) private static string FindHelpTopic(INamedValues values, string allTokens) { - var command = values.GetOrDefault("display.help.command", ""); - var option = values.GetOrDefault("display.help.option", ""); - var more = values.GetOrDefault("display.help.more", ""); + var command = values.GetOrEmpty("display.help.command"); + var option = values.GetOrEmpty("display.help.option"); + var more = values.GetOrEmpty("display.help.more"); - if (string.IsNullOrEmpty(command)) command = values.GetOrDefault("x.command", ""); + if (string.IsNullOrEmpty(command)) command = values.GetOrEmpty("x.command"); - string path = FindHelpFile(command, option, more); + string? path = FindHelpFile(command, option, more); string partial = command; while (path == null && partial.Contains(".")) @@ -404,16 +404,16 @@ private static string FindHelpTopic(INamedValues values, string allTokens) if (path == null && more == "help") path = FileHelpers.FindFileInHelpPath("help/help"); if (path == null) path = FileHelpers.FindFileInHelpPath("help/usage"); - return path; + return path!; } - private static string FindHelpFile(string command, string option, string more) + private static string? FindHelpFile(string command, string option, string more) { var hasCommand = !string.IsNullOrEmpty(command); var hasOption = !string.IsNullOrEmpty(option); var hasMore = !string.IsNullOrEmpty(more); - string path = hasCommand && hasOption && hasMore + string? path = hasCommand && hasOption && hasMore ? FileHelpers.FindFileInHelpPath($"help/{command}.{option}.{more}") : null; if (path == null && hasCommand && hasMore) path = FileHelpers.FindFileInHelpPath($"help/{command}.{more}"); diff --git a/src/common/details/commands/runjob_command.cs b/src/common/details/commands/runjob_command.cs index be70fd1c..9a6ed607 100644 --- a/src/common/details/commands/runjob_command.cs +++ b/src/common/details/commands/runjob_command.cs @@ -19,9 +19,8 @@ namespace Azure.AI.Details.Common.CLI { public class RunJobCommand : Command { - public RunJobCommand(ICommandValues values) + public RunJobCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } public bool RunCommand() @@ -36,36 +35,36 @@ private bool DoRunJob() var quiet = _values.GetOrDefault("x.quiet", false); - var args = _values.GetOrDefault("run.input.post.args", "").Replace(';', ' '); - var preArgs = _values.GetOrDefault("run.input.pre.args", "").Replace(';', ' '); + var args = _values.GetOrEmpty("run.input.post.args").Replace(';', ' '); + var preArgs = _values.GetOrEmpty("run.input.pre.args").Replace(';', ' '); - var process = _values.GetOrDefault("run.input.process", ""); + var process = _values.GetOrEmpty("run.input.process"); - var command = _values.GetOrDefault($"run.input.{Program.Name}.command", ""); - var commandArgs = _values.GetOrDefault($"run.input.{Program.Name}.post.command.args", "").Replace(';', ' '); - var preCommandArgs = _values.GetOrDefault($"run.input.{Program.Name}.pre.command.args", "").Replace(';', ' '); + var command = _values.GetOrEmpty($"run.input.{Program.Name}.command"); + var commandArgs = _values.GetOrEmpty($"run.input.{Program.Name}.post.command.args").Replace(';', ' '); + var preCommandArgs = _values.GetOrEmpty($"run.input.{Program.Name}.pre.command.args").Replace(';', ' '); - var job = _values.GetOrDefault($"run.input.{Program.Name}.job", ""); - var jobArgs = _values.GetOrDefault($"run.input.{Program.Name}.post.job.args", "").Replace(';', ' '); - var preJobArgs = _values.GetOrDefault($"run.input.{Program.Name}.pre.job.args", "").Replace(';', ' '); + var job = _values.GetOrEmpty($"run.input.{Program.Name}.job"); + var jobArgs = _values.GetOrEmpty($"run.input.{Program.Name}.post.job.args").Replace(';', ' '); + var preJobArgs = _values.GetOrEmpty($"run.input.{Program.Name}.pre.job.args").Replace(';', ' '); - var line = _values.GetOrDefault("run.input.line", ""); - var lineArgs = _values.GetOrDefault("run.input.post.line.args", "").Replace(';', ' '); - var preLineArgs = _values.GetOrDefault("run.input.pre.line.args", "").Replace(';', ' '); + var line = _values.GetOrEmpty("run.input.line"); + var lineArgs = _values.GetOrEmpty("run.input.post.line.args").Replace(';', ' '); + var preLineArgs = _values.GetOrEmpty("run.input.pre.line.args").Replace(';', ' '); - var script = _values.GetOrDefault("run.input.script", ""); - var scriptArgs = _values.GetOrDefault("run.input.post.script.args", "").Replace(';', ' '); - var preScriptArgs = _values.GetOrDefault("run.input.pre.script.args", "").Replace(';', ' '); + var script = _values.GetOrEmpty("run.input.script"); + var scriptArgs = _values.GetOrEmpty("run.input.post.script.args").Replace(';', ' '); + var preScriptArgs = _values.GetOrEmpty("run.input.pre.script.args").Replace(';', ' '); - var file = _values.GetOrDefault("run.input.file", ""); - var fileArgs = _values.GetOrDefault("run.input.post.file.args", "").Replace(';', ' '); - var preFileArgs = _values.GetOrDefault("run.input.pre.file.args", "").Replace(';', ' '); + var file = _values.GetOrEmpty("run.input.file"); + var fileArgs = _values.GetOrEmpty("run.input.post.file.args").Replace(';', ' '); + var preFileArgs = _values.GetOrEmpty("run.input.pre.file.args").Replace(';', ' '); - var item = _values.GetOrDefault("run.input.item", ""); - var itemArgs = _values.GetOrDefault("run.input.post.item.args", "").Replace(';', ' '); - var preItemArgs = _values.GetOrDefault("run.input.pre.item.args", "").Replace(';', ' '); + var item = _values.GetOrEmpty("run.input.item"); + var itemArgs = _values.GetOrEmpty("run.input.post.item.args").Replace(';', ' '); + var preItemArgs = _values.GetOrEmpty("run.input.pre.item.args").Replace(';', ' '); - var inputPath = _values.GetOrDefault("x.input.path", Directory.GetCurrentDirectory()); + var inputPath = _values.GetOrDefault("x.input.path", Directory.GetCurrentDirectory())!; var processOk = !string.IsNullOrEmpty(process); var commandOk = !string.IsNullOrEmpty(command); @@ -145,14 +144,14 @@ private bool DoRunJob() var retries = _values.GetOrDefault("run.retries", 0); var timeout = _values.GetOrDefault("run.timeout", 86400000); - var expected = _values.GetOrDefault("run.output.expect", ""); - var notExpected = _values.GetOrDefault("run.output.not.expect", ""); + var expected = _values.GetOrEmpty("run.output.expect"); + var notExpected = _values.GetOrEmpty("run.output.not.expect"); var autoExpect = _values.GetOrDefault("run.output.auto.expect", false); return DoRunJob(start.Trim(), startArgs.Trim(), startPath, expected, notExpected, autoExpect, timeout, retries); } - private bool UpdateProcessIfFileNotExist(string checkFileProcess, ref string process, string defaultProcess = null) + private bool UpdateProcessIfFileNotExist(string checkFileProcess, ref string process, string? defaultProcess = null) { if (!FileHelpers.FileExistsInDataPath(checkFileProcess, _values)) { @@ -170,7 +169,7 @@ private string UpdateJobStartPath(ref string job, string startPath) { var existing = FileHelpers.DemandFindFileInDataPath(job.Trim('@'), _values, "job"); var fi = new FileInfo(existing); - startPath = fi.DirectoryName; + startPath = fi.DirectoryName!; job = $"@{fi.Name}"; } return startPath; @@ -227,10 +226,14 @@ private int RunJobProcess(string start, string startArgs, string startPath, stri } var process = Process.Start(startInfo); + if (process == null) + { + _values.AddThrowError("ERROR:", $"Failed to start process: {start} {startArgs}"); + } return checkExpected || checkNotExpected || autoExpect - ? (CheckExpectedAsync(process, expected, notExpected, autoExpect, timeout).Result ? 0 : 4) - : (WaitForExit(process, timeout).Result ? process.ExitCode : 3); + ? (CheckExpectedAsync(process!, expected, notExpected, autoExpect, timeout).Result ? 0 : 4) + : (WaitForExit(process!, timeout).Result ? process!.ExitCode : 3); } private Task WaitForExit(Process process, int timeout) diff --git a/src/common/details/console/ColorHelpers.cs b/src/common/details/console/ColorHelpers.cs index 35ea2663..3de75d70 100644 --- a/src/common/details/console/ColorHelpers.cs +++ b/src/common/details/console/ColorHelpers.cs @@ -56,7 +56,7 @@ public static Colors GetErrorColors(ConsoleColor fg, ConsoleColor bg) return new Colors(colors[3], colors[2]); } - public static bool TryParseColorStyleText(string text, out Colors parsedStyle, out string parsedText) + public static bool TryParseColorStyleText(string text, out Colors? parsedStyle, out string? parsedText) { if (text.Length > 2 && text[0] == '#') { diff --git a/src/common/details/console/ConsoleHelpers.cs b/src/common/details/console/ConsoleHelpers.cs index 68527ec8..ae37a8a6 100644 --- a/src/common/details/console/ConsoleHelpers.cs +++ b/src/common/details/console/ConsoleHelpers.cs @@ -14,7 +14,7 @@ namespace Azure.AI.Details.Common.CLI { public static class ConsoleHelpers { - public static string ReadLineOrDefault(string defaultOnEmpty = "", string defaultOnEndOfRedirectedInput = null) + public static string? ReadLineOrDefault(string defaultOnEmpty = "", string? defaultOnEndOfRedirectedInput = null) { if (Console.IsInputRedirected) { @@ -120,11 +120,11 @@ public static void WriteLineWithHighlight(string text, char delimiter = '`') ColorHelpers.ResetColor(); Console.Write(part); } - else if (ColorHelpers.TryParseColorStyleText(part, out var colors, out text)) + else if (ColorHelpers.TryParseColorStyleText(part, out var colors, out var parsed)) { - Console.ForegroundColor = colors.Foreground; - Console.BackgroundColor = colors.Background; - Console.Write(text); + Console.ForegroundColor = colors!.Foreground; + Console.BackgroundColor = colors!.Background; + Console.Write(parsed); } else { @@ -140,7 +140,7 @@ public static void WriteLineWithHighlight(string text, char delimiter = '`') Console.WriteLine(); } - private static string stdinText = null; - private static byte[] stdinBytes = null; + private static string? stdinText = null; + private static byte[]? stdinBytes = null; } } diff --git a/src/common/details/console/gui/Screen.cs b/src/common/details/console/gui/Screen.cs index 7fccb0e5..af816e5a 100644 --- a/src/common/details/console/gui/Screen.cs +++ b/src/common/details/console/gui/Screen.cs @@ -239,8 +239,8 @@ public void WriteText(string text, int cch = int.MaxValue) public void WriteChar(int x, int y, char ch, int count = 1) { - Cursor saved1 = null; - Cursor saved2 = null; + Cursor? saved1 = null; + Cursor? saved2 = null; if (x + count > GetRightColumn()) { saved1 = new Cursor(GetLeftColumn(), GetTopRow()); @@ -280,11 +280,11 @@ public void WriteTextWithHighlight(Colors normal, Colors highlight, int x, int y var colorOn = false; foreach (var part in text.Split(delimiter)) { - if (colorOn && ColorHelpers.TryParseColorStyleText(part, out Colors parsed, out text)) + if (colorOn && ColorHelpers.TryParseColorStyleText(part, out var parsedColor, out var parsedText)) { - WriteText(parsed, x, y, text, cch); - cch -= text.Length; - x += text.Length; + WriteText(parsedColor!, x, y, parsedText!, cch); + cch -= parsedText!.Length; + x += parsedText!.Length; } else { diff --git a/src/common/details/console/gui/Window.cs b/src/common/details/console/gui/Window.cs index fee2ba2d..e2dbeea4 100644 --- a/src/common/details/console/gui/Window.cs +++ b/src/common/details/console/gui/Window.cs @@ -14,7 +14,7 @@ public class Borders public static string SingleLine = "\U0000250C\U00002500\U00002510\U00002502 \U00002502\U00002514\U00002500\U00002518"; } - public Window(Window parent, Rect rect, Colors colors, string border = null) + public Window(Window? parent, Rect rect, Colors colors, string? border = null) { this._parent = parent; @@ -26,7 +26,7 @@ public Window(Window parent, Rect rect, Colors colors, string border = null) #region parent and position - public Window GetParent() + public Window? GetParent() { return _parent; } @@ -70,7 +70,7 @@ public bool IsBorder() return _border != null; } - public string Border + public string? Border { get { return _border; } } @@ -271,7 +271,7 @@ public void WriteClientTextWithHighlight(Colors colors, Colors highlight, int x, #region protected methods - protected virtual void PaintWindow(Colors colors, string border = null) + protected virtual void PaintWindow(Colors colors, string? border = null) { if (border != null && border.Length == 9) { @@ -325,7 +325,7 @@ protected virtual void DispatchKeyEvents() #region private methods - private void SetRect(Rect rect) + private void SetRect(Rect rect) { this._rect = new Rect( rect.X + (_parent == null ? 0 : _parent.ClientRect.X), @@ -376,11 +376,11 @@ private void RestoreScreen() #region private data - private Window _parent; - private Rect _rect; - private Rect _rectClient; + private Window? _parent; + private Rect _rect = new Rect(0, 0, 0, 0); + private Rect _rectClient = new Rect(0, 0, 0, 0); private Colors _colors; - private string _border; + private string? _border; private bool _focus = false; private bool _open = false; private bool _killFocusCursorVisible = true; diff --git a/src/common/details/console/gui/controls/Control.cs b/src/common/details/console/gui/controls/Control.cs index 602b4131..609b367b 100644 --- a/src/common/details/console/gui/controls/Control.cs +++ b/src/common/details/console/gui/controls/Control.cs @@ -9,7 +9,7 @@ namespace Azure.AI.Details.Common.CLI.ConsoleGui { public class ControlWindow : Window { - public ControlWindow(Window parent, Rect rect, Colors colors, string border = null, bool enabled = true) : base(parent, rect, colors, border) + public ControlWindow(Window? parent, Rect rect, Colors colors, string? border = null, bool enabled = true) : base(parent, rect, colors, border) { this._enabled = enabled; } diff --git a/src/common/details/console/gui/controls/EditBoxControl.cs b/src/common/details/console/gui/controls/EditBoxControl.cs index 96e311cd..1c9327ad 100644 --- a/src/common/details/console/gui/controls/EditBoxControl.cs +++ b/src/common/details/console/gui/controls/EditBoxControl.cs @@ -9,12 +9,12 @@ namespace Azure.AI.Details.Common.CLI.ConsoleGui { public class EditBoxControl : ScrollingControl { - public EditBoxControl(Window parent, Rect rect, Colors color, string text, int uiMaxTextLengthParam, string picture, string pszBorder, bool fEnabled = true) : + public EditBoxControl(Window? parent, Rect rect, Colors color, string? text, int uiMaxTextLengthParam, string? picture, string? pszBorder, bool fEnabled = true) : base(parent, rect, color, pszBorder, fEnabled) { uiMaxTextLength = uiMaxTextLengthParam; - _text = text; + _text = text ?? string.Empty; _picture = picture; cursor.Save(); @@ -476,7 +476,7 @@ private bool TypeOverChar(char ch) string _text; int uiMaxTextLength; - string _picture; + string? _picture; Cursor cursor = new Cursor(); diff --git a/src/common/details/console/gui/controls/EditBoxQuickEdit.cs b/src/common/details/console/gui/controls/EditBoxQuickEdit.cs index dfd3a880..0aef58fb 100644 --- a/src/common/details/console/gui/controls/EditBoxQuickEdit.cs +++ b/src/common/details/console/gui/controls/EditBoxQuickEdit.cs @@ -10,7 +10,7 @@ namespace Azure.AI.Details.Common.CLI.ConsoleGui { public class EditBoxQuickEdit : EditBoxControl { - public static string Edit(int width, int height, Colors normal, string text = "", int maxCch = 1024, string picture = null, string border = null) + public static string? Edit(int width, int height, Colors normal, string? text = "", int maxCch = 1024, string? picture = null, string? border = null) { var rect = Screen.Current.MakeSpaceAtCursor(width, height); var editBox = new EditBoxQuickEdit(null, rect, normal, text, maxCch, picture, border); @@ -20,7 +20,7 @@ public static string Edit(int width, int height, Colors normal, string text = "" #region protected methods - protected EditBoxQuickEdit(Window parent, Rect rect, Colors colorNormal, string text = "", int maxCch = 1024, string picture = null, string border = null) : base(parent, rect, colorNormal, text, maxCch, picture, border, true) + protected EditBoxQuickEdit(Window? parent, Rect rect, Colors colorNormal, string? text = "", int maxCch = 1024, string? picture = null, string? border = null) : base(parent, rect, colorNormal, text, maxCch, picture, border, true) { } @@ -53,7 +53,7 @@ public override bool ProcessKey(ConsoleKeyInfo key) #region private data - private string _finalText; + private string? _finalText = null; #endregion } diff --git a/src/common/details/console/gui/controls/HelpViewer.cs b/src/common/details/console/gui/controls/HelpViewer.cs index e388ba4b..d80c96a5 100644 --- a/src/common/details/console/gui/controls/HelpViewer.cs +++ b/src/common/details/console/gui/controls/HelpViewer.cs @@ -77,9 +77,9 @@ public static void DisplayHelpText(string[] lines, int width, int height, Colors start.UseShellExecute = false; var process = Process.Start(start); - process.WaitForExit(); + process?.WaitForExit(); - if (process.ExitCode == 1) + if (process?.ExitCode == 1) { Environment.Exit(process.ExitCode); } @@ -105,7 +105,7 @@ public static void DisplayHelpText(string[] lines, int width, int height, Colors var programExe = OperatingSystem.IsWindows() ? Program.Exe : Program.Exe.Replace(".exe", ""); var start = new ProcessStartInfo(programExe, $"cls {tryCommand}"); start.UseShellExecute = false; - Process.Start(start).WaitForExit(); + Process.Start(start)?.WaitForExit(); Environment.Exit(1); } } @@ -124,7 +124,7 @@ public static void DisplayHelpTopics(string[] topics, int width, int height, Col var start = new ProcessStartInfo(programExe, $"quiet {helpCommand}"); start.UseShellExecute = false; - Process.Start(start).WaitForExit(); + Process.Start(start)?.WaitForExit(); } } @@ -147,11 +147,11 @@ public override bool ProcessKey(ConsoleKeyInfo key) #region protected methods - protected HelpViewer(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) + protected HelpViewer(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) { } - protected override void PaintWindow(Colors colors, string border = null) + protected override void PaintWindow(Colors colors, string? border = null) { base.PaintWindow(colors, border); if (border != null) diff --git a/src/common/details/console/gui/controls/ListBoxControl.cs b/src/common/details/console/gui/controls/ListBoxControl.cs index 2644e2dd..283df07f 100644 --- a/src/common/details/console/gui/controls/ListBoxControl.cs +++ b/src/common/details/console/gui/controls/ListBoxControl.cs @@ -10,7 +10,7 @@ namespace Azure.AI.Details.Common.CLI.ConsoleGui { public class ListBoxControl : VirtualListBoxControl { - public ListBoxControl(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) + public ListBoxControl(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) { } @@ -34,7 +34,7 @@ public virtual string GetDisplayText(int row) public override int GetNumRows() { return _rows < 0 - ? _rows = (Items != null ? Items.Length : 0) + ? _rows = Items.Length : _rows; } @@ -65,7 +65,7 @@ public override void DisplayRow(int row) private int _rows = -1; private int _columns = -1; - private string[] _items = null; + private string[] _items = Array.Empty(); #endregion } diff --git a/src/common/details/console/gui/controls/ListBoxPicker.cs b/src/common/details/console/gui/controls/ListBoxPicker.cs index 4cecb8e9..95b75607 100644 --- a/src/common/details/console/gui/controls/ListBoxPicker.cs +++ b/src/common/details/console/gui/controls/ListBoxPicker.cs @@ -46,13 +46,13 @@ public static int PickIndexOf(string[] lines, int width, int height, Colors norm return picker._picked; } - public static string PickString(string[] choices, int select = 0) + public static string? PickString(string[] choices, int select = 0) { var width = Math.Max(choices.Max(x => x.Length) + 4, 29); return ListBoxPicker.PickString(choices, width, 30, new Colors(ConsoleColor.White, ConsoleColor.Blue), new Colors(ConsoleColor.White, ConsoleColor.Red), select); } - public static string PickString(string[] lines, int width, int height, Colors normal, Colors selected, int select = 0) + public static string? PickString(string[] lines, int width, int height, Colors normal, Colors selected, int select = 0) { var picked = PickIndexOf(lines, width, height, normal, selected, select); return picked >= 0 && picked < lines.Length @@ -89,7 +89,7 @@ public override bool ProcessKey(ConsoleKeyInfo key) #region protected methods - protected ListBoxPicker(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) + protected ListBoxPicker(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) { } diff --git a/src/common/details/console/gui/controls/ScrollingControl.cs b/src/common/details/console/gui/controls/ScrollingControl.cs index f9233e21..2486ec94 100644 --- a/src/common/details/console/gui/controls/ScrollingControl.cs +++ b/src/common/details/console/gui/controls/ScrollingControl.cs @@ -43,7 +43,7 @@ public int ColumnOffset #region protected methods - protected ScrollingControl(Window parent, Rect rect, Colors colors, string border, bool fEnabled) : base(parent, rect, colors, border, fEnabled) + protected ScrollingControl(Window? parent, Rect rect, Colors colors, string? border, bool fEnabled) : base(parent, rect, colors, border, fEnabled) { _rowOffset = 0; _columnOffset = 0; diff --git a/src/common/details/console/gui/controls/SpeedSearchListBoxControl.cs b/src/common/details/console/gui/controls/SpeedSearchListBoxControl.cs index 3948f2a9..2d08a929 100644 --- a/src/common/details/console/gui/controls/SpeedSearchListBoxControl.cs +++ b/src/common/details/console/gui/controls/SpeedSearchListBoxControl.cs @@ -15,7 +15,7 @@ public class SpeedSearchListBoxControl : ListBoxControl { #region protected methods - protected SpeedSearchListBoxControl(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) + protected SpeedSearchListBoxControl(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) { } @@ -24,12 +24,12 @@ public override bool ProcessKey(ConsoleKeyInfo key) bool processed = base.ProcessKey(key); if (IsSpeedSearchOpen()) { - _speedSearchBox.DisplayCursor(); + _speedSearchBox!.DisplayCursor(); } return processed; } - protected override void PaintWindow(Colors colors, string border = null) + protected override void PaintWindow(Colors colors, string? border = null) { base.PaintWindow(colors, border); if (border != null) @@ -43,7 +43,7 @@ protected bool IsSpeedSearchOpen() return _speedSearchBox != null && _speedSearchBox.IsOpen(); } - protected bool OpenSpeedSearch(string text = null) + protected bool OpenSpeedSearch(string? text = null) { if (_speedSearchBox == null) { @@ -110,7 +110,7 @@ protected virtual string GetSpeedSearchTooltip() protected virtual string GetSpeedSearchText() { - return _speedSearchBox?.GetText(); + return _speedSearchBox?.GetText() ?? string.Empty; } protected bool ProcessSpeedSearchKey(ConsoleKeyInfo key) @@ -119,7 +119,7 @@ protected bool ProcessSpeedSearchKey(ConsoleKeyInfo key) { _speedSearchBox.Close(); _speedSearchBox = null; - PaintWindow(Colors, $"{Border.Substring(0, 4)}{(char)0}{Border.Substring(5)}"); + PaintWindow(Colors, $"{Border?.Substring(0, 4)}{(char)0}{Border?.Substring(5)}"); return true; } @@ -144,9 +144,9 @@ protected bool ProcessSpeedSearchKey(ConsoleKeyInfo key) if (key.IsAscii()) { OpenSpeedSearch(); - _speedSearchBox.End(); + _speedSearchBox!.End(); - if (_speedSearchBox.ProcessKey(key)) + if (_speedSearchBox!.ProcessKey(key)) { return SelectRowContaining(GetSpeedSearchText(), SelectedRow, true, true, true, true, +1); } @@ -256,10 +256,10 @@ protected bool RowContainsExactMatch(int row, string searchFor, out int col, out protected bool RowContainsRegex(int row, string searchFor, out int col, out int width) { var text = GetSpeedSearchText(row).ToLower(); - var matches = TryCatchHelpers.TryCatchNoThrow(() => Regex.Matches(text, searchFor), null, out _); + var matches = TryCatchHelpers.TryCatchNoThrow(() => Regex.Matches(text, searchFor), null, out _); var maxIndex = matches?.Count() > 0 ? matches?.Max(match => match.Index) : null; - var match = maxIndex.HasValue ? matches.Where(match => match.Index == maxIndex).Last() : null; + var match = maxIndex.HasValue ? matches?.Where(match => match.Index == maxIndex).Last() : null; col = match != null && match.Success ? match.Index : -1; width = match != null && match.Success ? match.Length : -1; @@ -290,7 +290,7 @@ protected bool SetSelectedSpeedSearchRow(int row, int col, int width) if (IsSpeedSearchOpen()) { - _speedSearchBox.DisplayCursor(); + _speedSearchBox!.DisplayCursor(); } return selected; @@ -300,7 +300,7 @@ protected bool SetSelectedSpeedSearchRow(int row, int col, int width) #region private data - private EditBoxControl _speedSearchBox; + private EditBoxControl? _speedSearchBox; #endregion } diff --git a/src/common/details/console/gui/controls/TextViewerControl.cs b/src/common/details/console/gui/controls/TextViewerControl.cs index 963a050a..e9f1b375 100644 --- a/src/common/details/console/gui/controls/TextViewerControl.cs +++ b/src/common/details/console/gui/controls/TextViewerControl.cs @@ -102,7 +102,7 @@ public override void DisplayRow(int row) #region protected methods - protected TextViewerControl(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) + protected TextViewerControl(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, colorSelected, border, fEnabled) { } diff --git a/src/common/details/console/gui/controls/VirtualListBoxControl.cs b/src/common/details/console/gui/controls/VirtualListBoxControl.cs index 0c45e0bc..38c3b8f3 100644 --- a/src/common/details/console/gui/controls/VirtualListBoxControl.cs +++ b/src/common/details/console/gui/controls/VirtualListBoxControl.cs @@ -9,7 +9,7 @@ namespace Azure.AI.Details.Common.CLI.ConsoleGui { abstract public class VirtualListBoxControl : ScrollingControl { - protected VirtualListBoxControl(Window parent, Rect rect, Colors colorNormal, Colors colorSelected, string border = null, bool fEnabled = true) : base(parent, rect, colorNormal, border, fEnabled) + protected VirtualListBoxControl(Window? parent, Rect rect, Colors colorNormal, Colors colorSelected, string? border = null, bool fEnabled = true) : base(parent, rect, colorNormal, border, fEnabled) { this.colorsSelected = colorSelected; } diff --git a/src/common/details/console/gui_helpers/ask_prompt_helper.cs b/src/common/details/console/gui_helpers/ask_prompt_helper.cs index 7ad51f97..4788708d 100644 --- a/src/common/details/console/gui_helpers/ask_prompt_helper.cs +++ b/src/common/details/console/gui_helpers/ask_prompt_helper.cs @@ -10,7 +10,7 @@ namespace Azure.AI.Details.Common.CLI { public class AskPromptHelper { - public static string AskPrompt(string prompt, string value = null, bool useEditBox = false) + public static string? AskPrompt(string prompt, string? value = null, bool useEditBox = false) { Console.Write(prompt); diff --git a/src/common/details/console/gui_helpers/name_picker_helpers.cs b/src/common/details/console/gui_helpers/name_picker_helpers.cs index afd4ff30..6d72f24c 100644 --- a/src/common/details/console/gui_helpers/name_picker_helpers.cs +++ b/src/common/details/console/gui_helpers/name_picker_helpers.cs @@ -13,7 +13,7 @@ namespace Azure.AI.Details.Common.CLI { public class NameGenHelper { - public static string GenerateName(string userName = null, int maxCch = 24) + public static string GenerateName(string? userName = null, int maxCch = 24) { EnsureLoaded(); @@ -30,9 +30,9 @@ public static string GenerateName(string userName = null, int maxCch = 24) for (int i = 0; i < maxTries; i++) { - var animal = GetRandomElement(_animals); - var color = GetRandomElement(_colors); - var adjective = GetRandomElement(_adjectives); + var animal = GetRandomElement(_animals!); + var color = GetRandomElement(_colors!); + var adjective = GetRandomElement(_adjectives!); var name = approach switch { @@ -73,9 +73,9 @@ private static void EnsureLoaded() } } - private static string[] LoadFrom(string fileName) + private static string[] LoadFrom(string fromFileName) { - fileName = $"help/include.text.{fileName}"; + var fileName = $"help/include.text.{fromFileName}"; fileName = FileHelpers.FindFileInHelpPath(fileName); var text = !string.IsNullOrEmpty(fileName) @@ -91,23 +91,23 @@ private static string GetRandomElement(string[] array) return array[index]; } - private static string[] _adjectives = null; - private static string[] _colors = null; - private static string[] _animals = null; + private static string[]? _adjectives = null; + private static string[]? _colors = null; + private static string[]? _animals = null; private static readonly Random _random = new Random(); } public class NamePickerHelper { - public static string DemandPickOrEnterName(string namePrompt, string nameOutKind, string nameIn = null, string nameInKind = null, string userName = null, int maxCch = 32) + public static string? DemandPickOrEnterName(string namePrompt, string nameOutKind, string? nameIn = null, string? nameInKind = null, string? userName = null, int maxCch = 32) { var choices = GetNameChoices(nameIn, nameInKind, nameOutKind, userName, maxCch); var usePicker = choices != null && choices.Count() > 1; while (usePicker) { - choices.Insert(0, "(Regenerate choices)"); + choices!.Insert(0, "(Regenerate choices)"); Console.Write(namePrompt); var pick = ListBoxPicker.PickIndexOf(choices.ToArray()); @@ -134,13 +134,13 @@ public static string DemandPickOrEnterName(string namePrompt, string nameOutKind while (true) { var name = DemandAskPrompt(namePrompt); - if (name.Length > maxCch) + if (name?.Length > maxCch) { Console.WriteLine($"*** WARNING: Name is too long. Max length is {maxCch}.\n"); continue; } - if (name.Count(x => !char.IsLetterOrDigit(x) && x != '-') > 0) + if (name?.Count(x => !char.IsLetterOrDigit(x) && x != '-') > 0) { Console.WriteLine($"*** WARNING: Name contains invalid characters. Only letters, digits, and dashes are allowed.\n"); continue; @@ -150,29 +150,29 @@ public static string DemandPickOrEnterName(string namePrompt, string nameOutKind } } - private static List GetNameChoices(string nameIn, string nameInKind, string nameOutKind, string userName, int maxCch) + private static List GetNameChoices(string? nameIn, string? nameInKind, string nameOutKind, string? userName, int maxCch) { var choices = new List(); var nameInOk = !string.IsNullOrEmpty(nameIn) && !string.IsNullOrEmpty(nameInKind); if (nameInOk) { - nameIn = nameIn.Trim().Replace("_", "-"); + nameIn = nameIn!.Trim().Replace("_", "-"); } - if (nameInOk && nameIn.StartsWith($"{nameInKind}-")) + if (nameInOk && nameIn!.StartsWith($"{nameInKind}-")) { - var nameBase = nameIn.Substring(nameInKind.Length + 1); + var nameBase = nameIn.Substring(nameInKind!.Length + 1); choices.Add($"{nameOutKind}-{nameBase}"); } - if (nameInOk && nameIn.EndsWith($"-{nameInKind}")) + if (nameInOk && nameIn!.EndsWith($"-{nameInKind}")) { - var nameBase = nameIn.Substring(0, nameIn.Length - nameInKind.Length - 1); + var nameBase = nameIn.Substring(0, nameIn.Length - nameInKind!.Length - 1); choices.Add($"{nameBase}-{nameOutKind}"); } - if (nameInOk && nameIn.Contains($"-{nameInKind}-")) + if (nameInOk && nameIn!.Contains($"-{nameInKind}-")) { var nameBase = nameIn.Replace($"-{nameInKind}-", $"-{nameOutKind}-"); choices.Add(nameBase); @@ -199,7 +199,7 @@ private static List GetNameChoices(string nameIn, string nameInKind, str return choices; } - private static string DemandAskPrompt(string prompt, string value = null, bool useEditBox = false) + private static string? DemandAskPrompt(string prompt, string? value = null, bool useEditBox = false) { var answer = AskPromptHelper.AskPrompt(prompt, value, useEditBox); if (string.IsNullOrEmpty(answer)) diff --git a/src/common/details/helpers/config_set_helpers.cs b/src/common/details/helpers/config_set_helpers.cs index be530468..cbab4ee7 100644 --- a/src/common/details/helpers/config_set_helpers.cs +++ b/src/common/details/helpers/config_set_helpers.cs @@ -31,31 +31,41 @@ public static void ConfigCognitiveServicesAIServicesKindResource(string subscrip Console.WriteLine(); int maxLabelWidth = 0; - var actions = new List>(new Action[] { - ConfigSetLambda("@services.endpoint", endpoint, "Endpoint (AIServices)", endpoint, ref maxLabelWidth), - ConfigSetLambda("@services.key", key, "Key (AIServices)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@services.region", region, "Region (AIServices)", region, ref maxLabelWidth), + var actions = new List>(); + + actions.Add(ConfigSetLambda("@services.endpoint", endpoint, "Endpoint (AIServices)", endpoint, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@services.key", key, "Key (AIServices)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@services.region", region, "Region (AIServices)", region, ref maxLabelWidth)); - ConfigSetLambda("@chat.key", key, "Key (chat)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@chat.region", region, "Region (chat)", region, ref maxLabelWidth), - ConfigSetLambda("@chat.endpoint", endpoint, "Endpoint (chat)", endpoint, ref maxLabelWidth), - chatDeployment.HasValue ? ConfigSetLambda("@chat.deployment", chatDeployment.Value.Name, "Deployment (chat)", chatDeployment.Value.Name, ref maxLabelWidth) : null, - chatDeployment.HasValue ? ConfigSetLambda("@chat.model", chatDeployment.Value.ModelName, "Model Name (chat)", chatDeployment.Value.ModelName, ref maxLabelWidth) : null, + actions.Add(ConfigSetLambda("@chat.key", key, "Key (chat)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.region", region, "Region (chat)", region, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.endpoint", endpoint, "Endpoint (chat)", endpoint, ref maxLabelWidth)); + if (chatDeployment != null) + { + actions.Add(ConfigSetLambda("@chat.deployment", chatDeployment.Value.Name, "Deployment (chat)", chatDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.model", chatDeployment.Value.ModelName, "Model Name (chat)", chatDeployment.Value.ModelName, ref maxLabelWidth)); + } - ConfigSetLambda("@search.embedding.key", key, "Key (embedding)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@search.embedding.endpoint", endpoint, "Endpoint (embedding)", endpoint, ref maxLabelWidth), - embeddingsDeployment.HasValue ? ConfigSetLambda("@search.embedding.model.deployment.name", embeddingsDeployment.Value.Name, "Deployment (embedding)", embeddingsDeployment.Value.Name, ref maxLabelWidth) : null, - embeddingsDeployment.HasValue ? ConfigSetLambda("@search.embedding.model.name", embeddingsDeployment.Value.ModelName, "Model Name (embedding)", embeddingsDeployment.Value.ModelName, ref maxLabelWidth) : null, + actions.Add(ConfigSetLambda("@search.embedding.key", key, "Key (embedding)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@search.embedding.endpoint", endpoint, "Endpoint (embedding)", endpoint, ref maxLabelWidth)); + if (embeddingsDeployment != null) + { + actions.Add(ConfigSetLambda("@search.embedding.model.deployment.name", embeddingsDeployment.Value.Name, "Deployment (embedding)", embeddingsDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@search.embedding.model.name", embeddingsDeployment.Value.ModelName, "Model Name (embedding)", embeddingsDeployment.Value.ModelName, ref maxLabelWidth)); + } - ConfigSetLambda("@chat.evaluation.key", key, "Key (evaluation)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@chat.evaluation.endpoint", endpoint, "Endpoint (evaluation)", endpoint, ref maxLabelWidth), - evaluationDeployment.HasValue ? ConfigSetLambda("@chat.evaluation.model.deployment.name", evaluationDeployment.Value.Name, "Deployment (evaluation)", evaluationDeployment.Value.Name, ref maxLabelWidth) : null, - evaluationDeployment.HasValue ? ConfigSetLambda("@chat.evaluation.model.name", evaluationDeployment.Value.ModelName, "Model Name (evaluation)", evaluationDeployment.Value.ModelName, ref maxLabelWidth) : null, + actions.Add(ConfigSetLambda("@chat.evaluation.key", key, "Key (evaluation)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.evaluation.endpoint", endpoint, "Endpoint (evaluation)", endpoint, ref maxLabelWidth)); + if (evaluationDeployment != null) + { + actions.Add(ConfigSetLambda("@chat.evaluation.model.deployment.name", evaluationDeployment.Value.Name, "Deployment (evaluation)", evaluationDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.evaluation.model.name", evaluationDeployment.Value.ModelName, "Model Name (evaluation)", evaluationDeployment.Value.ModelName, ref maxLabelWidth)); + } + + actions.Add(ConfigSetLambda("@speech.endpoint", endpoint, "Endpoint (speech)", endpoint, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@speech.key", key, "Key (speech)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@speech.region", region, "Region (speech)", region, ref maxLabelWidth)); - ConfigSetLambda("@speech.endpoint", endpoint, "Endpoint (speech)", endpoint, ref maxLabelWidth), - ConfigSetLambda("@speech.key", key, "Key (speech)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@speech.region", region, "Region (speech)", region, ref maxLabelWidth), - }); actions.ForEach(x => x?.Invoke(maxLabelWidth)); } @@ -83,24 +93,34 @@ public static void ConfigOpenAiResource(string subscriptionId, string region, st Console.WriteLine(); int maxLabelWidth = 0; - var actions = new List>(new Action[] { - ConfigSetLambda("@chat.key", key, "Key (chat)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@chat.endpoint", endpoint, "Endpoint (chat)", endpoint, ref maxLabelWidth), - chatDeployment.HasValue ? ConfigSetLambda("@chat.deployment", chatDeployment.Value.Name, "Deployment (chat)", chatDeployment.Value.Name, ref maxLabelWidth) : null, - chatDeployment.HasValue ? ConfigSetLambda("@chat.model", chatDeployment.Value.ModelName, "Model Name (chat)", chatDeployment.Value.ModelName, ref maxLabelWidth) : null, - - ConfigSetLambda("@search.embedding.key", key, "Key (embedding)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@search.embedding.endpoint", endpoint, "Endpoint (embedding)", endpoint, ref maxLabelWidth), - embeddingsDeployment.HasValue ? ConfigSetLambda("@search.embedding.model.deployment.name", embeddingsDeployment.Value.Name, "Deployment (embedding)", embeddingsDeployment.Value.Name, ref maxLabelWidth) : null, - embeddingsDeployment.HasValue ? ConfigSetLambda("@search.embedding.model.name", embeddingsDeployment.Value.ModelName, "Model Name (embedding)", embeddingsDeployment.Value.ModelName, ref maxLabelWidth) : null, - - ConfigSetLambda("@chat.evaluation.key", key, "Key (evaluation)", key.Substring(0, 4) + "****************************", ref maxLabelWidth), - ConfigSetLambda("@chat.evaluation.endpoint", endpoint, "Endpoint (evaluation)", endpoint, ref maxLabelWidth), - evaluationDeployment.HasValue ? ConfigSetLambda("@chat.evaluation.model.deployment.name", evaluationDeployment.Value.Name, "Deployment (evaluation)", evaluationDeployment.Value.Name, ref maxLabelWidth) : null, - evaluationDeployment.HasValue ? ConfigSetLambda("@chat.evaluation.model.name", evaluationDeployment.Value.ModelName, "Model Name (evaluation)", evaluationDeployment.Value.ModelName, ref maxLabelWidth) : null, - - ConfigSetLambda("@chat.region", region, "Region", region, ref maxLabelWidth), - }); + var actions = new List>(); + + actions.Add(ConfigSetLambda("@chat.key", key, "Key (chat)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.endpoint", endpoint, "Endpoint (chat)", endpoint, ref maxLabelWidth)); + if (chatDeployment != null) + { + actions.Add(ConfigSetLambda("@chat.deployment", chatDeployment.Value.Name, "Deployment (chat)", chatDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.model", chatDeployment.Value.ModelName, "Model Name (chat)", chatDeployment.Value.ModelName, ref maxLabelWidth)); + } + + actions.Add(ConfigSetLambda("@search.embedding.key", key, "Key (embedding)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@search.embedding.endpoint", endpoint, "Endpoint (embedding)", endpoint, ref maxLabelWidth)); + if (embeddingsDeployment != null) + { + actions.Add(ConfigSetLambda("@search.embedding.model.deployment.name", embeddingsDeployment.Value.Name, "Deployment (embedding)", embeddingsDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@search.embedding.model.name", embeddingsDeployment.Value.ModelName, "Model Name (embedding)", embeddingsDeployment.Value.ModelName, ref maxLabelWidth)); + } + + actions.Add(ConfigSetLambda("@chat.evaluation.key", key, "Key (evaluation)", key.Substring(0, 4) + "****************************", ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.evaluation.endpoint", endpoint, "Endpoint (evaluation)", endpoint, ref maxLabelWidth)); + if (evaluationDeployment != null) + { + actions.Add(ConfigSetLambda("@chat.evaluation.model.deployment.name", evaluationDeployment.Value.Name, "Deployment (evaluation)", evaluationDeployment.Value.Name, ref maxLabelWidth)); + actions.Add(ConfigSetLambda("@chat.evaluation.model.name", evaluationDeployment.Value.ModelName, "Model Name (evaluation)", evaluationDeployment.Value.ModelName, ref maxLabelWidth)); + } + + actions.Add(ConfigSetLambda("@chat.region", region, "Region", region, ref maxLabelWidth)); + actions.ForEach(x => x?.Invoke(maxLabelWidth)); } diff --git a/src/common/details/helpers/expect_helper.cs b/src/common/details/helpers/expect_helper.cs index c6fd4640..93cb7abf 100644 --- a/src/common/details/helpers/expect_helper.cs +++ b/src/common/details/helpers/expect_helper.cs @@ -24,8 +24,8 @@ public static async Task CheckExpectedLinesAsync(IAsyncEnumerable { // use the existing (unhooked) console output, for auto expect Action writeLine = Console.WriteLine; - Action autoExpectOutput = autoExpect ? writeLine : null; - TextWriter echoStdOutWriter = echoStdOut ? Console.Out : null; + Action? autoExpectOutput = autoExpect ? writeLine : null; + TextWriter? echoStdOutWriter = echoStdOut ? Console.Out : null; // instance the helper, and await it's completion var helper = new ExpectHelper(lines, expected, unexpected, autoExpectOutput, echoStdOutWriter, Console.Out); @@ -48,15 +48,15 @@ public static async Task CheckExpectedConsoleOutputAsync(Func consol // use the original console output, for auto expect and echoing output Action writeLine = oldStdOut.WriteLine; - Action autoExpectOutput = autoExpect ? writeLine : null; - TextWriter echoStdOutWriter = echoStdOut ? oldStdOut : null; + Action? autoExpectOutput = autoExpect ? writeLine : null; + TextWriter? echoStdOutWriter = echoStdOut ? oldStdOut : null; // instance the helper, and start the ExpectAsync task var helper = new ExpectHelper(allLines, expected, unexpected, autoExpectOutput, echoStdOutWriter, oldStdOut); var expectTask = helper.ExpectAsync(); // run the function, safely - var funcResult = TryCatchHelpers.TryCatchNoThrow(consoleOutputProducingFunction, false, out Exception functionThrewException); + var funcResult = TryCatchHelpers.TryCatchNoThrow(consoleOutputProducingFunction, false, out var functionThrewException); // now ... close the console output, restoring the original // this will trigger the end of expectation input @@ -95,8 +95,8 @@ public static async Task CheckExpectedConsoleOutputAsync(Process process, // use the existing (unhooked) console output, for auto expect and echoing output Action writeLine = Console.WriteLine; - Action autoExpectOutput = autoExpect ? writeLine : null; - TextWriter echoStdOutWriter = echoStdOut ? Console.Out : null; + Action? autoExpectOutput = autoExpect ? writeLine : null; + TextWriter? echoStdOutWriter = echoStdOut ? Console.Out : null; // instance the helper, and await it's completion var helper = new ExpectHelper(allLines, expected, unexpected, autoExpectOutput, echoStdOutWriter, Console.Out); @@ -105,7 +105,7 @@ public static async Task CheckExpectedConsoleOutputAsync(Process process, #region private methods - private ExpectHelper(IAsyncEnumerable lines, IEnumerable expected, IEnumerable unexpected, Action autoExpectOutput, TextWriter echoStdOutWriter, TextWriter errorWriter) + private ExpectHelper(IAsyncEnumerable lines, IEnumerable expected, IEnumerable unexpected, Action? autoExpectOutput, TextWriter? echoStdOutWriter, TextWriter errorWriter) { this.allLines = lines; this.expected = expected != null ? new Queue(expected) : null; @@ -130,7 +130,7 @@ private async Task ExpectAsync() if (!allExpectedFound && errorWriter != null) { ColorHelpers.SetErrorColors(); - errorWriter.WriteLine($"UNEXPECTED: Couldn't find '{expected.Peek()}' in:\n```\n{unmatchedInput}```"); + errorWriter.WriteLine($"UNEXPECTED: Couldn't find '{expected!.Peek()}' in:\n```\n{unmatchedInput}```"); ColorHelpers.ResetColor(); } @@ -144,13 +144,13 @@ private void AutoExpectOutput(string line) .Replace(".", "\\.").Replace("?", "\\?") .Replace("[", "\\[").Replace("]", "\\]") .Replace("(", "\\(").Replace(")", "\\)"); - autoExpectOutput($"^{regexEscapedLine}\\r?$\\n"); + autoExpectOutput!($"^{regexEscapedLine}\\r?$\\n"); } private void CheckExpected(string line) { unmatchedInput.AppendLine(line); - while (expected.Count > 0) + while (expected!.Count > 0) { var pattern = expected.Peek(); var check = unmatchedInput.ToString(); @@ -165,7 +165,7 @@ private void CheckExpected(string line) private void CheckUnexpected(string line) { - foreach (var pattern in unexpected) + foreach (var pattern in unexpected!) { var match = Regex.Match(line, pattern); if (!match.Success) continue; // check more patterns @@ -187,33 +187,33 @@ private void CheckUnexpected(string line) private StringBuilder unmatchedInput = new StringBuilder(); private IAsyncEnumerable allLines; - private Queue expected; - private List unexpected; + private Queue? expected; + private List? unexpected; bool foundUnexpected = false; - private Action autoExpectOutput; - private TextWriter echoStdOutWriter; - private TextWriter errorWriter; + private Action? autoExpectOutput; + private TextWriter? echoStdOutWriter; + private TextWriter? errorWriter; #endregion #region future - public static async Task ExpectAsync(Func> input, IEnumerable expected, IEnumerable unexpected, Action autoExpectOutput) - { - var expectedItems = expected != null ? new Queue(expected) : null; - var unexpectedItems = unexpected != null ? new List(unexpected) : null; - var helper = new ExpectHelper(input, expectedItems, unexpectedItems, autoExpectOutput); - return await helper.ExpectAsync(); - } - - private ExpectHelper(Func> input, Queue expected, List unexpected, Action autoExpectOutput) - { - // this.readAllLinesAsync = input; - // this.expected = expected; - // this.unexpected = unexpected; - // this.autoExpectOutput = autoExpectOutput; - } + // public static async Task ExpectAsync(Func> input, IEnumerable? expected, IEnumerable? unexpected, Action? autoExpectOutput) + // { + // var expectedItems = expected != null ? new Queue(expected) : null; + // var unexpectedItems = unexpected != null ? new List(unexpected) : null; + // var helper = new ExpectHelper(input, expectedItems, unexpectedItems, autoExpectOutput); + // return await helper.ExpectAsync(); + // } + + // private ExpectHelper(Func> input, Queue? expected, List? unexpected, Action? autoExpectOutput) + // { + // // this.readAllLinesAsync = input; + // // this.expected = expected; + // // this.unexpected = unexpected; + // // this.autoExpectOutput = autoExpectOutput; + // } #endregion } diff --git a/src/common/details/helpers/file_helpers.cs b/src/common/details/helpers/file_helpers.cs index 091ef6fa..977664f2 100644 --- a/src/common/details/helpers/file_helpers.cs +++ b/src/common/details/helpers/file_helpers.cs @@ -17,7 +17,7 @@ namespace Azure.AI.Details.Common.CLI { public class PathHelpers { - public static string Combine(string path1, string path2) + public static string? Combine(string path1, string path2) { try { @@ -29,7 +29,7 @@ public static string Combine(string path1, string path2) } } - public static string Combine(string path1, string path2, string path3) + public static string? Combine(string path1, string path2, string path3) { try { @@ -46,8 +46,11 @@ public static IEnumerable Combine(string path1, IEnumerable path var list = new List(); foreach (var path2 in path2s) { + var combined = PathHelpers.Combine(path1, path2); + if (combined == null) continue; + list.Add(!string.IsNullOrEmpty(path2) - ? PathHelpers.Combine(path1, path2) + ? combined : path1); } return list; @@ -67,10 +70,10 @@ public class FileHelpers { public static void UpdatePaths(INamedValues values) { - var outputPath = values.GetOrDefault("x.output.path", ""); + var outputPath = values.GetOrEmpty("x.output.path"); SetOutputPath(outputPath); - var inputPath = values.GetOrDefault("x.input.path", outputPath); + var inputPath = values.GetOrDefault("x.input.path", outputPath)!; SetInputPath(inputPath); } @@ -79,15 +82,19 @@ public static string AppendToFileName(string fileName, string appendBeforeExtens if (IsStandardInputReference(fileName) || IsStandardOutputReference(fileName)) return fileName; var file = new FileInfo(fileName); - return Path.Combine(file.DirectoryName, $"{Path.GetFileNameWithoutExtension(file.FullName)}{appendBeforeExtension}{file.Extension}{appendAfterExtension}"); + var dirName = file.DirectoryName ?? string.Empty; + return Path.Combine(dirName, $"{Path.GetFileNameWithoutExtension(file.FullName)}{appendBeforeExtension}{file.Extension}{appendAfterExtension}"); } - public static IEnumerable FindFiles(string path, string pattern, INamedValues values = null, bool checkOverrides = true, bool checkResources = true) + public static IEnumerable FindFiles(string path, string pattern, INamedValues? values = null, bool checkOverrides = true, bool checkResources = true) { - return FindFiles(PathHelpers.Combine(path, pattern), values, checkOverrides, checkResources); + var combined = PathHelpers.Combine(path, pattern); + return combined != null + ? FindFiles(combined, values, checkOverrides, checkResources) + : Enumerable.Empty(); } - public static IEnumerable FindFiles(string fileNames, INamedValues values = null, bool checkOverrides = true, bool checkResources = true) + public static IEnumerable FindFiles(string fileNames, INamedValues? values = null, bool checkOverrides = true, bool checkResources = true) { var currentDir = Directory.GetCurrentDirectory(); foreach (var item in fileNames.Split(new char[] { ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) @@ -122,7 +129,7 @@ public static IEnumerable FindFiles(string fileNames, INamedValues value var path = !hasPath ? currentDir : item.Substring(0, pathLen); var pattern = !hasPath ? item : item.Substring(pathLen + 1); - EnumerationOptions recursiveOptions = null; + EnumerationOptions? recursiveOptions = null; if (path.EndsWith("**")) { path = path.Substring(0, path.Length - 2).TrimEnd('/', '\\'); @@ -232,7 +239,7 @@ public static IEnumerable FindFilesInDataPath(string fileNames, INamedVa return found; } - public static IEnumerable FindFilesInTemplatePath(string fileNames, INamedValues values) + public static IEnumerable FindFilesInTemplatePath(string fileNames, INamedValues? values) { if (Program.Debug) Console.WriteLine($"DEBUG: Searching for TEMPLATE '{fileNames}'\n"); @@ -243,7 +250,7 @@ public static IEnumerable FindFilesInTemplatePath(string fileNames, INam return found; } - private static IEnumerable FindFilesInPath(string fileNames, INamedValues values, string searchPath) + private static IEnumerable FindFilesInPath(string fileNames, INamedValues? values, string searchPath) { var commandActual = values?.GetCommand(); var commandScope = values?.GetOrDefault("x.config.scope.command", commandActual == "config" ? "" : commandActual); @@ -285,8 +292,8 @@ public static void PrintFoundFiles(List found, INamedValues values, bool var fi = exists ? new FileInfo(item) : null; var i = item.LastIndexOfAny(slash); - var name = exists ? fi.Name : item.Substring(i + 1); - var location = exists ? fi.DirectoryName : item.Substring(0, i > 0 ? i : item.Length); + var name = exists ? fi?.Name : item.Substring(i + 1); + var location = exists ? fi?.DirectoryName : item.Substring(0, i > 0 ? i : item.Length); if (!quiet && location != lastLocation && showLocation) { @@ -392,7 +399,7 @@ private static string DemandFindFileInPath(string fileName, INamedValues values, ? $"Cannot find input file: \"{fileName}\"" : $"Cannot find {fileKind} file: \"{fileName}\""); } - return existing; + return existing!; } private static string CheckStripDotSlash(string check) @@ -402,7 +409,7 @@ private static string CheckStripDotSlash(string check) : check; } - public static string FindFileInConfigPath(string fileName, INamedValues values) + public static string? FindFileInConfigPath(string fileName, INamedValues values) { if (Program.Debug) Console.WriteLine($"DEBUG: CONFIG '{fileName}' EXIST?\n"); @@ -413,7 +420,7 @@ public static string FindFileInConfigPath(string fileName, INamedValues values) return found; } - public static string FindFileInDataPath(string fileName, INamedValues values) + public static string? FindFileInDataPath(string fileName, INamedValues values) { if (Program.Debug) Console.WriteLine($"DEBUG: DATA '{fileName}' EXIST?\n"); @@ -424,7 +431,7 @@ public static string FindFileInDataPath(string fileName, INamedValues values) return found; } - public static string FindFileInTemplatePath(string fileName, INamedValues values) + public static string? FindFileInTemplatePath(string fileName, INamedValues values) { if (Program.Debug) Console.WriteLine($"DEBUG: TEMPLATE '{fileName}' EXIST?\n"); @@ -435,7 +442,7 @@ public static string FindFileInTemplatePath(string fileName, INamedValues values return found; } - public static string FindFileInHelpPath(string fileName) + public static string? FindFileInHelpPath(string fileName) { if (Program.Debug) Console.WriteLine($"DEBUG: HELP '{fileName}' EXIST?\n"); @@ -446,7 +453,7 @@ public static string FindFileInHelpPath(string fileName) return found; } - public static string FindFileInOsPath(string fileName) + public static string? FindFileInOsPath(string fileName) { return FindFilesInOsPath(fileName).FirstOrDefault(); } @@ -468,7 +475,7 @@ public static IEnumerable FindFilesInOsPath(string fileName) return found; } - private static string FindFileInPath(string fileName, INamedValues values, string searchPaths) + private static string? FindFileInPath(string fileName, INamedValues? values, string searchPaths) { if (IsStandardInputReference(fileName)) return fileName; @@ -484,13 +491,13 @@ private static string FindFileInPath(string fileName, INamedValues values, strin foreach (string path in paths) { var existing = FindFileInScope(regionScope, commandScope, path, fileName, values); - if (FileExists(existing)) return CheckStripDotSlash(existing); + if (FileExists(existing)) return CheckStripDotSlash(existing!); } return null; } - public static bool FileExistsInConfigPath(string fileName, INamedValues values) + public static bool FileExistsInConfigPath(string fileName, INamedValues? values) { return FileExistsInPath(fileName, values, GetConfigPath(values)); } @@ -516,17 +523,17 @@ public static bool FileExistsInOsPath(string fileName) return existing != null; } - private static bool FileExistsInPath(string fileName, INamedValues values, string searchPath) + private static bool FileExistsInPath(string fileName, INamedValues? values, string searchPath) { var existing = FindFileInPath(fileName, values, searchPath); return existing != null; } - public static string ExpandAtFileValue(string atFileValue, INamedValues values = null) + public static string ExpandAtFileValue(string atFileValue, INamedValues? values = null) { if (atFileValue.StartsWith("@") && FileHelpers.FileExistsInConfigPath(atFileValue[1..], values)) { - return FileHelpers.ReadAllText(FileHelpers.DemandFindFileInConfigPath(atFileValue[1..], values, "configuration"), Encoding.UTF8); + return FileHelpers.ReadAllText(FileHelpers.DemandFindFileInConfigPath(atFileValue[1..], values!, "configuration"), Encoding.UTF8); } else if (atFileValue.StartsWith("@") && FileHelpers.IsStandardInputReference(atFileValue[1..])) { @@ -551,17 +558,15 @@ public static byte[] ReadAllBytes(string fileName) public static string ReadAllText(string fileName, Encoding encoding) { - var text = IsStandardInputReference(fileName) - ? ConsoleHelpers.ReadAllStandardInputText() - : IsOverride(fileName) - ? ReadAllOverrideText(fileName) - : IsResource(fileName) - ? ReadAllResourceText(fileName, encoding ?? Encoding.Default) - : File.ReadAllText(fileName, encoding ?? Encoding.Default); + string? text = null; + if (text == null && IsStandardInputReference(fileName)) text = ConsoleHelpers.ReadAllStandardInputText(); + if (text == null && IsOverride(fileName)) text = ReadAllOverrideText(fileName); + if (text == null && IsResource(fileName)) text = ReadAllResourceText(fileName, encoding ?? Encoding.Default); + if (text == null) text = File.ReadAllText(fileName, encoding ?? Encoding.Default); return text.Trim('\r', '\n'); } - public static string GetOutputConfigFileName(string file, INamedValues values = null) + public static string GetOutputConfigFileName(string file, INamedValues? values = null) { file = file.TrimStart('@'); @@ -578,9 +583,8 @@ public static bool IsStandardOutputReference(string fileName) return fileName == "-" || fileName == "stdout"; } - public static string GetOutputDataFileName(string file, INamedValues values = null) + public static string GetOutputDataFileName(string file, INamedValues? values = null) { - if (file == null) return null; if (file.StartsWith("@")) return GetOutputConfigFileName(file, values); if (IsStandardOutputReference(file)) return file; @@ -589,8 +593,10 @@ public static string GetOutputDataFileName(string file, INamedValues values = nu var hasPath = i1 >= 0 || i2 >= 0; var pathLen = hasPath ? Math.Max(i1, i2) : 0; - var outputDir = values != null ? values.GetOrDefault("x.output.path", _outputPath) : _outputPath; - var outputFile = !hasPath ? PathHelpers.Combine(outputDir, file) : file; + var outputDir = values != null ? values.GetOrDefault("x.output.path", _outputPath)! : _outputPath; + var outputFile = !hasPath + ? PathHelpers.Combine(outputDir, file) ?? file + : file; if (Program.Debug) Console.WriteLine($"DEBUG: Output DATA file '{file}'='{outputFile}'"); @@ -734,7 +740,7 @@ public static string CheckOutputJson(string text, INamedValues values, string do return text; } - public static string ReadWriteAllStream(Stream stream, string fileName, string message, bool returnAsText) + public static string? ReadWriteAllStream(Stream stream, string fileName, string? message, bool returnAsText) { // we need to know if we're writing to standard output var isStandardOutput = IsStandardOutputReference(fileName); @@ -754,7 +760,7 @@ public static string ReadWriteAllStream(Stream stream, string fileName, string m } // get the file stream - var fileStream = FileHelpers.Create(fileName); + var fileStream = FileHelpers.Create(fileName!); // copy data from the source stream to the file stream int read; @@ -766,7 +772,7 @@ public static string ReadWriteAllStream(Stream stream, string fileName, string m } // if we need to return the text, or we need to print to stdout - string text = null; + string? text = null; if (returnAsText || isStandardOutput) { // seek back and read the text @@ -779,7 +785,7 @@ public static string ReadWriteAllStream(Stream stream, string fileName, string m // dispose the file stream, and delete the temporary file fileStream.Dispose(); - if (useTemp) File.Delete(fileName); + if (useTemp) File.Delete(fileName!); // print the "I'm done" message... if (message != null) Console.WriteLine($"{message} Done!\n"); @@ -793,32 +799,35 @@ public static void EnsureDirectoryForFileExists(string fileName) if (IsStandardInputReference(fileName)) return; if (IsStandardOutputReference(fileName)) return; - string dir = Path.GetDirectoryName(fileName); + var dir = Path.GetDirectoryName(fileName); if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) { Directory.CreateDirectory(dir); } } - public static void CopyFile(string path1, string file1, string path2, string file2 = null, bool verbose = true) + public static bool TryCopyFile(string path1, string file1, string path2, string? file2 = null, bool verbose = true) { if (file2 == null) file2 = file1; var source = PathHelpers.Combine(path1, file1); if (!FileExists(source)) source = PathHelpers.Combine(path1, ".." + Path.DirectorySeparatorChar + file1); if (!FileExists(source)) source = PathHelpers.Combine(path1, ".." + Path.DirectorySeparatorChar + ".." + Path.DirectorySeparatorChar + file1); - if (!FileExists(source)) return; + if (!FileExists(source)) return false; if (verbose) Console.WriteLine($" Saving {file2} ... "); var dest = PathHelpers.Combine(path2, file2); - FileHelpers.EnsureDirectoryForFileExists(dest); + if (dest == null) return false; - File.Copy(source, dest, true); + FileHelpers.EnsureDirectoryForFileExists(dest); + File.Copy(source!, dest, true); + return true; } - public static void CopyFiles(IEnumerable sourceLocations, string[] files, string destinationLocation, string dllNewPrefix, string dllNewSuffix, bool verbose) + public static void TryCopyFiles(IEnumerable sourceLocations, string[] files, string destinationLocation, string? dllNewPrefix, string? dllNewSuffix, bool verbose) { + var count = 0; var remapDlls = !string.IsNullOrEmpty(dllNewPrefix) && !string.IsNullOrEmpty(dllNewSuffix); foreach (var location in sourceLocations) { @@ -828,7 +837,7 @@ public static void CopyFiles(IEnumerable sourceLocations, string[] files ? $"{dllNewPrefix}{file.Substring(0, file.Length - 4)}{dllNewSuffix}" : file; - FileHelpers.CopyFile(location, fileName, destinationLocation, null, verbose); + count += FileHelpers.TryCopyFile(location, fileName, destinationLocation, null, verbose) ? 1 : 0; } } } @@ -838,11 +847,12 @@ public static FileInfo GetAssemblyFileInfo(Type type) // GetAssembly.Location always returns empty when the project is built as // a single-file app (which we do when publishing the Dependency package), // warning IL3000 - string assemblyPath = Assembly.GetAssembly(type).Location; + var assembly = Assembly.GetAssembly(type); + string assemblyPath = assembly?.Location ?? string.Empty; if (assemblyPath == string.Empty) { assemblyPath = AppContext.BaseDirectory; - assemblyPath += Assembly.GetAssembly(type).GetName().Name + ".dll"; + assemblyPath += assembly?.GetName().Name + ".dll"; } return new FileInfo(assemblyPath); } @@ -851,7 +861,7 @@ public static void LogException(ICommandValues values, Exception ex) { var file = $"exception.{{run.time}}.{{pid}}.{{time}}.{Program.Name}.error.log"; - var runTime = values.GetOrDefault("x.run.time", ""); + var runTime = values.GetOrEmpty("x.run.time"); file = file.Replace("{run.time}", runTime); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -864,7 +874,7 @@ public static void LogException(ICommandValues values, Exception ex) FileHelpers.WriteAllText(file, ex.ToString(), Encoding.UTF8); } - public static bool FileExists(string fileName) + public static bool FileExists(string? fileName) { if (string.IsNullOrEmpty(fileName)) return false; @@ -933,7 +943,7 @@ public static IEnumerable FindOverrides(string find) yield break; } - private static string ReadAllOverrideText(string fileName) + private static string? ReadAllOverrideText(string fileName) { if (!IsOverride(fileName)) return null; @@ -1062,7 +1072,7 @@ private static Dictionary GetOriginalResourceFileNames() return _origDotXfileNamesDictionary; } - private static Stream GetResourceStream(string fileName) + private static Stream? GetResourceStream(string fileName) { var resource = ResourceNameFromFileName(fileName); return Program.ResourceAssembly.GetManifestResourceStream(resource) @@ -1071,7 +1081,7 @@ private static Stream GetResourceStream(string fileName) private static string ReadAllResourceText(string fileName, Encoding encoding) { - var stream = GetResourceStream(fileName); + var stream = GetResourceStream(fileName)!; var length = stream.Length; byte[] buffer = new byte[length]; @@ -1085,7 +1095,7 @@ private static string ReadAllResourceText(string fileName, Encoding encoding) private static byte[] ReadAllResourceBytes(string fileName) { - var stream = GetResourceStream(fileName); + var stream = GetResourceStream(fileName)!; var length = stream.Length; byte[] buffer = new byte[length]; @@ -1123,13 +1133,7 @@ public static byte[] ReadAllStreamBytes(Stream stream) } - private static void FindFilesInScope(List files, string region, string command, string path1, string path2, string fileName, INamedValues values) - { - var path = PathHelpers.Combine(path1, path2); - FindFilesInScope(files, region, command, path, fileName, values); - } - - private static void FindFilesInScope(List files, string region, string command, string path, string fileName, INamedValues values) + private static void FindFilesInScope(List files, string? region, string? command, string path, string fileName, INamedValues? values) { if (!string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(command)) { @@ -1152,50 +1156,44 @@ private static void FindFilesInScope(List files, string region, string c files.AddRange(FindFiles(path, fileName, values)); } - private static string FindFileInScope(string region, string command, string path1, string path2, string fileName, INamedValues values) - { - var path = PathHelpers.Combine(path1, path2); - return FindFileInScope(region, command, path, fileName, values); - } - - private static string FindFileInScope(string region, string command, string path, string fileName, INamedValues values) + private static string? FindFileInScope(string? region, string? command, string path, string fileName, INamedValues? values) { fileName = fileName.ReplaceValues(values); return FindFileInScope(region, command, path, fileName); } - private static string FindFileInScope(string region, string command, string path, string fileName) + private static string? FindFileInScope(string? region, string? command, string path, string fileName) { if (!string.IsNullOrEmpty(region) && !string.IsNullOrEmpty(command)) { var scoped = PathHelpers.Combine(path, $"{region}.{command}.{fileName}"); - if (FileExists(scoped)) return CheckStripDotSlash(scoped); + if (FileExists(scoped)) return CheckStripDotSlash(scoped!); } if (!string.IsNullOrEmpty(region)) { var scoped = PathHelpers.Combine(path, $"{region}.{fileName}"); - if (FileExists(scoped)) return CheckStripDotSlash(scoped); + if (FileExists(scoped)) return CheckStripDotSlash(scoped!); } if (!string.IsNullOrEmpty(command)) { var scoped = PathHelpers.Combine(path, $"{command}.{fileName}"); - if (FileExists(scoped)) return CheckStripDotSlash(scoped); + if (FileExists(scoped)) return CheckStripDotSlash(scoped!); } - fileName = PathHelpers.Combine(path, fileName); - if (FileExists(fileName)) return CheckStripDotSlash(fileName); + fileName = PathHelpers.Combine(path, fileName) ?? string.Empty; + if (FileExists(fileName)) return CheckStripDotSlash(fileName!); return null; } - private static string ExistingPathOrNull(string check, string root = null, int checkParentDepth = 4) + private static string? ExistingPathOrNull(string check, string? root = null, int checkParentDepth = 4) { if (Directory.Exists(check)) return check; if (Path.IsPathFullyQualified(check)) return null; - var combined = Path.Combine(root, check); + var combined = Path.Combine(root ?? string.Empty, check); if (Directory.Exists(combined)) return combined; var parent = checkParentDepth > 0 && root != null ? Directory.GetParent(root) : null; @@ -1229,7 +1227,7 @@ private static void SetOutputPath(string outputPath) } } - private static string GetConfigPath(INamedValues values = null) + private static string GetConfigPath(INamedValues? values = null) { var cwd = Directory.GetCurrentDirectory(); if (_configPathCalculatedFrom != cwd) @@ -1255,7 +1253,7 @@ private static string GetConfigPath(INamedValues values = null) return _configPath; } - private static void CheckScopedConfigPath(INamedValues values) + private static void CheckScopedConfigPath(INamedValues? values) { if (_configPathScoped != null) return; @@ -1285,7 +1283,7 @@ private static string ExpandConfigPath(string path0, string paths) return path0.TrimEnd(';') + ";" + sb.ToString().TrimEnd(';'); } - public static string GetConfigOutputDir(INamedValues values = null) + public static string GetConfigOutputDir(INamedValues? values = null) { CheckScopedConfigOutputDir(values); if (!string.IsNullOrEmpty(_configOutputDirScoped)) return _configOutputDirScoped; @@ -1304,7 +1302,7 @@ public static string GetConfigOutputDir(INamedValues values = null) return _configOutputDir; } - private static void CheckScopedConfigOutputDir(INamedValues values) + private static void CheckScopedConfigOutputDir(INamedValues? values) { if (_configOutputDirScoped != null) return; @@ -1341,7 +1339,7 @@ private static string GetScopedConfigDotDir(string hive, bool mustExist = true, return dotdir; } - public static string HiveFromFileName(string fileName) + public static string? HiveFromFileName(string fileName) { fileName = fileName.Replace('/', '\\'); var system = GetAssemblyConfigDotDir(false, false).Replace('/', '\\'); @@ -1447,12 +1445,12 @@ private static string CheckDotDirectory(string checkPath, bool mustExist = true, private const string defaultDataPath = @";./;../;../../;../../../;../../../../;{config.path};"; - private static string _configPathCalculatedFrom = null; - private static string _configPath = null; - private static string _configPathScoped = null; + private static string? _configPathCalculatedFrom = null; + private static string? _configPath = null; + private static string? _configPathScoped = null; - private static string _configOutputDir = null; - private static string _configOutputDirScoped = null; + private static string? _configOutputDir = null; + private static string? _configOutputDirScoped = null; private static string _dataPath = defaultDataPath; private static string _outputPath = ""; @@ -1460,6 +1458,6 @@ private static string CheckDotDirectory(string checkPath, bool mustExist = true, private static readonly string dotDirectory = $".{Program.Name}/"; private static ReaderWriterLockSlim _lockSlim = new ReaderWriterLockSlim(); - private static Dictionary _origDotXfileNamesDictionary; + private static Dictionary? _origDotXfileNamesDictionary; } } diff --git a/src/common/details/helpers/http_helpers.cs b/src/common/details/helpers/http_helpers.cs index 4bf978ed..f7534f6e 100644 --- a/src/common/details/helpers/http_helpers.cs +++ b/src/common/details/helpers/http_helpers.cs @@ -21,7 +21,7 @@ public static string DownloadFile(string url) return DownloadFile(url, $"Downloading {url}...", null); } - public static string DownloadFile(string url, string message, INamedValues values) + public static string DownloadFile(string url, string message, INamedValues? values) { var verbose = values != null && values.GetOrDefault("x.verbose", true); if (verbose && !string.IsNullOrEmpty(message)) Console.WriteLine(message); @@ -49,7 +49,7 @@ public static string DownloadFile(string url, string message, INamedValues value var invalidSaveAs = saveAs == null || File.Exists(saveAs) || saveAs.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0; if (invalidSaveAs) saveAs = Path.GetTempFileName(); - var fileStream = FileHelpers.Create(saveAs); + var fileStream = FileHelpers.Create(saveAs!); int read = 0; while ((read = stream.Read(buffer, 0, bufferSize)) != 0) @@ -63,12 +63,12 @@ public static string DownloadFile(string url, string message, INamedValues value if (verbose && !string.IsNullOrEmpty(message)) Console.WriteLine($"{message} Done!\n"); - return saveAs; + return saveAs!; } - public static string DownloadFileWithRetry(string url, int timeOutRetries = 10) + public static string? DownloadFileWithRetry(string url, int timeOutRetries = 10) { - string downloaded = null; + string? downloaded = null; TryCatchHelpers.TryCatchRetry( () => downloaded = DownloadFile(url), (ex) => ex.Message.Contains("timed") && ex.Message.Contains("out"), @@ -76,9 +76,9 @@ public static string DownloadFileWithRetry(string url, int timeOutRetries = 10) return downloaded; } - public static string DownloadFileWithRetry(string url, string message, INamedValues values, int timeOutRetries = 10) + public static string? DownloadFileWithRetry(string url, string message, INamedValues values, int timeOutRetries = 10) { - string downloaded = null; + string? downloaded = null; TryCatchHelpers.TryCatchRetry( () => downloaded = DownloadFile(url, message, values), (ex) => ex.Message.Contains("timed") && ex.Message.Contains("out"), @@ -100,7 +100,7 @@ public static string GetWebRequestNoBodyAsString(HttpWebRequest request) return sb.ToString(); } - public static string WriteOutputRequest(HttpWebRequest request, string filename, string payload = null, bool append = false) + public static string? WriteOutputRequest(HttpWebRequest request, string filename, string? payload = null, bool append = false) { var text = GetWebRequestNoBodyAsString(request); @@ -108,7 +108,7 @@ public static string WriteOutputRequest(HttpWebRequest request, string filename, if (append) FileHelpers.AppendAllText(filename, text, Encoding.UTF8); var payloadOk = !string.IsNullOrEmpty(payload); - if (payloadOk) FileHelpers.AppendAllText(filename, payload, Encoding.UTF8); + if (payloadOk) FileHelpers.AppendAllText(filename, payload!, Encoding.UTF8); return payload; } @@ -122,7 +122,7 @@ public static byte[] WriteOutputRequest(HttpWebRequest request, string filename, return payload; } - public static HttpWebResponse GetWebResponse(HttpWebRequest request, string payload = null) + public static HttpWebResponse GetWebResponse(HttpWebRequest request, string? payload = null) { if (!string.IsNullOrEmpty(payload)) { @@ -183,9 +183,9 @@ public static bool WaitForComplete(Func createWebRequest, INamed var response = HttpHelpers.GetWebResponse(request); var json = HttpHelpers.ReadWriteJson(response, values, domain); - var parsed = JsonDocument.Parse(json); + var parsed = json != null ? JsonDocument.Parse(json) : null; - var status = parsed.GetPropertyStringOrNull("status"); + var status = parsed?.GetPropertyStringOrNull("status"); switch (status) { case "success": @@ -226,7 +226,7 @@ public static bool WaitForComplete(Func createWebRequest, INamed return passed; } - public static string ReadWriteJson(WebResponse response, INamedValues values, string domain, bool skipWrite = false) + public static string? ReadWriteJson(WebResponse? response, INamedValues values, string domain, bool skipWrite = false) { if (response == null) return null; @@ -237,7 +237,7 @@ public static string ReadWriteJson(WebResponse response, INamedValues values, st return isJson ? text : null; } - public static string GetOutputDataFileName(string defaultFileName, HttpWebResponse response, ICommandValues values, string domain, out bool isText, out bool isJson) + public static string? GetOutputDataFileName(string? defaultFileName, HttpWebResponse response, ICommandValues values, string domain, out bool isText, out bool isJson) { isText = response.ContentType.Contains("text/plain"); isJson = response.ContentType.Contains("application/json"); @@ -248,13 +248,13 @@ public static string GetOutputDataFileName(string defaultFileName, HttpWebRespon : HttpHelpers.GetFileNameFromResponse(response, values); } - var fileName = values.GetOrDefault($"{domain}.output.file", defaultFileName); + var fileName = values.GetOrDefault($"{domain}.output.file", defaultFileName)!; return FileHelpers.GetOutputDataFileName(fileName, values); } public static string GetFileNameFromResponse(WebResponse response, INamedValues values) { - var runtime = values.GetOrDefault("x.run.time", ""); + var runtime = values.GetOrEmpty("x.run.time"); var defaultFileName = $"{runtime}.downloaded"; var path = response.ResponseUri.LocalPath; @@ -265,14 +265,14 @@ public static string GetFileNameFromResponse(WebResponse response, INamedValues return lastPartValid ? lastPart : defaultFileName; } - public static string ReadWriteResponse(WebResponse response, string fileName, string message, bool returnAsText) + public static string? ReadWriteResponse(WebResponse response, string fileName, string message, bool returnAsText) { Stream stream; using (stream = response.GetResponseStream()) return FileHelpers.ReadWriteAllStream(stream, fileName, message, returnAsText); } - public static string GetLatestVersionInfo(INamedValues values, string domain) + public static string? GetLatestVersionInfo(INamedValues values, string domain) { try { @@ -281,10 +281,10 @@ public static string GetLatestVersionInfo(INamedValues values, string domain) request.Method = WebRequestMethods.Http.Get; var response = HttpHelpers.GetWebResponse(request); var json = HttpHelpers.ReadWriteJson(response, values, domain); - var info = JsonDocument.Parse(json); - var versionList = info.GetPropertyArrayOrEmpty("versions"); + var info = !string.IsNullOrEmpty(json) ? JsonDocument.Parse(json) : null; + var versionList = info?.GetPropertyArrayOrEmpty("versions"); - return versionList.Last().GetString(); + return versionList?.Last().GetString(); } catch (Exception) { diff --git a/src/common/details/helpers/json_helpers.cs b/src/common/details/helpers/json_helpers.cs index 66ed3eeb..2299ea8f 100644 --- a/src/common/details/helpers/json_helpers.cs +++ b/src/common/details/helpers/json_helpers.cs @@ -27,18 +27,18 @@ public static string GetPropertyStringOrEmpty(this JsonElement element, string n if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value)) { return value.ValueKind == JsonValueKind.String - ? value.GetString() + ? value.GetString() ?? string.Empty : value.GetRawText(); } return string.Empty; } - public static string GetPropertyStringOrNull(this JsonDocument document, string name) + public static string? GetPropertyStringOrNull(this JsonDocument document, string name) { return document.RootElement.GetPropertyStringOrNull(name); } - public static string GetPropertyStringOrNull(this JsonElement element, string name) + public static string? GetPropertyStringOrNull(this JsonElement element, string name) { if (element.ValueKind == JsonValueKind.Object && element.TryGetProperty(name, out var value)) { @@ -132,7 +132,7 @@ public static string MakeString(string value) public static string MakeString(INamedValues values, string valueName) { - var value = values.GetOrDefault(valueName, ""); + var value = values.GetOrEmpty(valueName); return MakeString(value); } @@ -145,7 +145,7 @@ public static string MakeStringOrEmpty(string value) public static string MakeStringOrEmpty(INamedValues values, string valueName) { - var value = values.GetOrDefault(valueName, ""); + var value = values.GetOrEmpty(valueName); return MakeStringOrEmpty(value); } @@ -161,14 +161,14 @@ public static string MakeStringArray(string delimitedValues, string delimiters) public static string MakeStringArray(INamedValues values, string delimitedValuesName, string delimiters) { - var delimitedValues = values.GetOrDefault(delimitedValuesName, ""); + var delimitedValues = values.GetOrEmpty(delimitedValuesName); return MakeStringArray(delimitedValues, delimiters); } public static string MakeStringArray(INamedValues values, string singleValueName, string delimitedValuesName, string delimiters) { - var singleValue = values.GetOrDefault(singleValueName, ""); - var delimitedValues = values.GetOrDefault(delimitedValuesName, ""); + var singleValue = values.GetOrEmpty(singleValueName); + var delimitedValues = values.GetOrEmpty(delimitedValuesName); return MakeStringArray($"{singleValue};{delimitedValues}", delimiters); } @@ -182,14 +182,14 @@ public static string MakeStringArrayOrEmpty(string delimitedValues, string delim public static string MakeStringArrayOrEmpty(INamedValues values, string delimitedValuesName, string delimiters) { - var delimitedValues = values.GetOrDefault(delimitedValuesName, ""); + var delimitedValues = values.GetOrEmpty(delimitedValuesName); return MakeStringArrayOrEmpty(delimitedValues, delimiters); } public static string MakeStringArrayOrEmpty(INamedValues values, string singleValueName, string delimitedValuesName, string delimiters) { - var singleValue = values.GetOrDefault(singleValueName, ""); - var delimitedValues = values.GetOrDefault(delimitedValuesName, ""); + var singleValue = values.GetOrEmpty(singleValueName); + var delimitedValues = values.GetOrEmpty(delimitedValuesName); var singleOk = !string.IsNullOrEmpty(singleValue); var delimitedOk = !string.IsNullOrEmpty(delimitedValues); @@ -290,7 +290,7 @@ public static string ContinueWithStringArrayMemberOrEmpty(string name, INamedVal #endregion - public static void PrintJson(string text, string indent = " ", bool naked = false) + public static void PrintJson(string? text, string indent = " ", bool naked = false) { if (!string.IsNullOrWhiteSpace(text)) { diff --git a/src/common/details/helpers/log_helpers.cs b/src/common/details/helpers/log_helpers.cs index 2ffe9e8a..df39cf13 100644 --- a/src/common/details/helpers/log_helpers.cs +++ b/src/common/details/helpers/log_helpers.cs @@ -22,7 +22,7 @@ public static void EnsureStartLogFile(ICommandValues values) var time = DateTime.Now.ToFileTime().ToString(); if (log.Contains("{time}")) log = log.Replace("{time}", time); - var runTime = values.GetOrDefault("x.run.time", ""); + var runTime = values.GetOrEmpty("x.run.time"); if (log.Contains("{run.time}")) log = log.Replace("{run.time}", runTime); try diff --git a/src/common/details/helpers/process_helpers.cs b/src/common/details/helpers/process_helpers.cs index 0264e1c2..0a20d039 100644 --- a/src/common/details/helpers/process_helpers.cs +++ b/src/common/details/helpers/process_helpers.cs @@ -31,12 +31,12 @@ public ParsedJsonProcessOutput(ProcessOutput output) } public ProcessOutput Output; - public T Payload; + public T? Payload; } public class ProcessHelpers { - public static Process StartBrowser(string url) + public static Process? StartBrowser(string url) { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? Process.Start(new ProcessStartInfo("cmd", $"/c start {url.Replace("&", "^&")}") { CreateNoWindow = true }) @@ -47,7 +47,7 @@ public static Process StartBrowser(string url) : null; } - public static Process StartProcess(string fileName, string arguments, Dictionary addToEnvironment = null, bool redirectOutput = true, bool redirectInput = false) + public static Process? StartProcess(string fileName, string arguments, Dictionary? addToEnvironment = null, bool redirectOutput = true, bool redirectInput = false) { var start = new ProcessStartInfo(fileName, arguments); start.UseShellExecute = false; @@ -66,7 +66,7 @@ public static Process StartProcess(string fileName, string arguments, Dictionary return Process.Start(start); } - public static async Task RunShellScriptAsync(string inlineScriptOrFileName, bool scriptIsBash = false, Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null, Action mergedOutputHandler = null, bool captureOutput = true, bool interactive = false) + public static async Task RunShellScriptAsync(string inlineScriptOrFileName, bool scriptIsBash = false, Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null, Action? mergedOutputHandler = null, bool captureOutput = true, bool interactive = false) { ProcessOutput processOutput; var useBinBash = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows); @@ -105,7 +105,7 @@ public static async Task RunShellScriptAsync(string inlineScriptO return processOutput; } - public static async Task RunShellInteractiveAsync(Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null, Action mergedOutputHandler = null, bool captureOutput = true) + public static async Task RunShellInteractiveAsync(Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null, Action? mergedOutputHandler = null, bool captureOutput = true) { var interactiveShellFileName = !OS.IsWindows() ? "bash" : "cmd.exe"; var interactiveShellArguments = !OS.IsWindows() ? "-li" : "/k PROMPT (ai dev shell) %PROMPT%& title (ai dev shell)"; @@ -113,7 +113,7 @@ public static async Task RunShellInteractiveAsync(Dictionary RunShellCommandAsync(string command, string arguments, Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null, Action mergedOutputHandler = null, bool captureOutput = true) + public static async Task RunShellCommandAsync(string command, string arguments, Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null, Action? mergedOutputHandler = null, bool captureOutput = true) { SHELL_DEBUG_TRACE($"COMMAND: {command} {arguments} {DictionaryToString(addToEnvironment)}"); @@ -125,7 +125,7 @@ public static async Task RunShellCommandAsync(string command, str var sbErr = new StringBuilder(); var sbMerged = new StringBuilder(); - var stdOutReceived = (string data) => { + var stdOutReceived = (string? data) => { if (data != null) { sbOut.AppendLine(data); @@ -138,7 +138,7 @@ public static async Task RunShellCommandAsync(string command, str outDoneSignal.Set(); } }; - var stdErrReceived = (string data) => { + var stdErrReceived = (string? data) => { if (data != null) { sbErr.AppendLine(data); @@ -152,7 +152,7 @@ public static async Task RunShellCommandAsync(string command, str } }; - Process process; + Process? process; try { process = StartShellCommandProcess(command, arguments, addToEnvironment, redirectOutput); @@ -167,27 +167,30 @@ public static async Task RunShellCommandAsync(string command, str }; } - if (redirectOutput) + if (process != null) { - process.OutputDataReceived += (sender, e) => stdOutReceived(e.Data); - process.ErrorDataReceived += (sender, e) => stdErrReceived(e.Data); - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - } + if (redirectOutput) + { + process.OutputDataReceived += (sender, e) => stdOutReceived(e.Data); + process.ErrorDataReceived += (sender, e) => stdErrReceived(e.Data); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + } - await process.WaitForExitAsync(); + await process.WaitForExitAsync(); - if (redirectOutput) - { - outDoneSignal.WaitOne(); - errDoneSignal.WaitOne(); + if (redirectOutput) + { + outDoneSignal.WaitOne(); + errDoneSignal.WaitOne(); + } } var output = new ProcessOutput(); output.StdOutput = sbOut.ToString().Trim(' ', '\r', '\n'); output.StdError = sbErr.ToString().Trim(' ', '\r', '\n'); output.MergedOutput = sbMerged.ToString().Trim(' ', '\r', '\n'); - output.ExitCode = process.ExitCode; + output.ExitCode = process?.ExitCode ?? -1; if (!string.IsNullOrEmpty(output.StdOutput)) SHELL_DEBUG_TRACE($"---\nSTDOUT\n---\n{output.StdOutput}"); if (!string.IsNullOrEmpty(output.StdError)) SHELL_DEBUG_TRACE($"---\nSTDERR\n---\n{output.StdError}"); @@ -195,7 +198,7 @@ public static async Task RunShellCommandAsync(string command, str return output; } - public static async Task> ParseShellCommandJson(string command, string arguments, Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null) + public static async Task> ParseShellCommandJson(string command, string arguments, Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null) { var processOutput = await RunShellCommandAsync(command, arguments, addToEnvironment, stdOutHandler, stdErrHandler); var stdOutput = processOutput.StdOutput; @@ -205,7 +208,7 @@ public static async Task> ParseShellCommand : new ParsedJsonProcessOutput(processOutput); } - private static Process StartShellCommandProcess(string command, string arguments, Dictionary addToEnvironment = null, bool captureOutput = true) + private static Process? StartShellCommandProcess(string command, string arguments, Dictionary? addToEnvironment = null, bool captureOutput = true) { var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); return isWindows @@ -221,7 +224,7 @@ private static void SHELL_DEBUG_TRACE(string message,[CallerLineNumber] int line AI.DBG_TRACE_INFO(message, line, caller, file); } - private static string DictionaryToString(Dictionary dictionary) + private static string DictionaryToString(Dictionary? dictionary) { var kvps = new List(); if (dictionary != null) diff --git a/src/common/details/helpers/python_runner.cs b/src/common/details/helpers/python_runner.cs index 15fd09cf..bd64e18b 100644 --- a/src/common/details/helpers/python_runner.cs +++ b/src/common/details/helpers/python_runner.cs @@ -15,7 +15,7 @@ namespace Azure.AI.Details.Common.CLI { public class PythonRunner { - public static async Task RunPythonScriptAsync(string script, string args = null, Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null, Action mergedOutputHandler = null) + public static async Task RunPythonScriptAsync(string script, string? args = null, Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null, Action? mergedOutputHandler = null) { EnsureFindPython(); if (_pythonBinary == null) @@ -25,7 +25,7 @@ public static async Task RunPythonScriptAsync(string script, stri return new ProcessOutput() { ExitCode = -1 }; } - string tempFile = null; + string? tempFile = null; try { @@ -44,9 +44,15 @@ public static async Task RunPythonScriptAsync(string script, stri } } - public static string RunEmbeddedPythonScript(ICommandValues values, string scriptName, string scriptArgs = null, Dictionary addToEnvironment = null, Action stdOutHandler = null, Action stdErrHandler = null, Action mergedOutputHandler = null) + public static string RunEmbeddedPythonScript(ICommandValues values, string scriptName, string? scriptArgs = null, Dictionary? addToEnvironment = null, Action? stdOutHandler = null, Action? stdErrHandler = null, Action? mergedOutputHandler = null) { var path = FileHelpers.FindFileInHelpPath($"help/include.python.script.{scriptName}.py"); + if (path == null) + { + values.AddThrowError("ERROR:", $"Python script '{scriptName}' not found!"); + return string.Empty; + } + var script = FileHelpers.ReadAllHelpText(path, Encoding.UTF8); if (Program.Debug) @@ -83,7 +89,7 @@ public static string RunEmbeddedPythonScript(ICommandValues values, string scrip if (output.Contains("MESSAGE:") && output.Contains("EXCEPTION:") && output.Contains("TRACEBACK:")) { var messageLine = process.StdError.Split(new[] { '\r', '\n' }).FirstOrDefault(x => x.StartsWith("MESSAGE:")); - var message = messageLine.Substring("MESSAGE:".Length).Trim(); + var message = messageLine?.Substring("MESSAGE:".Length)?.Trim(); FileHelpers.LogException(values, new PythonScriptException(output, exit)); if (output.Contains("az login")) @@ -171,12 +177,14 @@ public static string RunEmbeddedPythonScript(ICommandValues values, string scrip info.Add($"Python script failed! (exit code={exit})"); info.Add(""); info.Add("OUTPUT:"); - info.Add(output); + info.Add(output ?? string.Empty); values.AddThrowError(info[0], info[1], info.Skip(2).ToArray()); } - return ParseOutputAndSkipLinesUntilStartsWith(output, "---").Trim('\r', '\n', ' '); + return output != null + ? ParseOutputAndSkipLinesUntilStartsWith(output, "---").Trim('\r', '\n', ' ') + : string.Empty; } private static string ParseOutputAndSkipLinesUntilStartsWith(string output, string startsWith) @@ -198,7 +206,7 @@ private static string ParseOutputAndSkipLinesUntilStartsWith(string output, stri return sb.ToString(); } - private static string EnsureFindPython() + private static string? EnsureFindPython() { if (_pythonBinary == null) { @@ -208,10 +216,10 @@ private static string EnsureFindPython() return _pythonBinary; } - private static string FindPython() + private static string? FindPython() { - string fullPath = FindPythonBinaryInOsPath(); - string pythonExec = fullPath; + var fullPath = FindPythonBinaryInOsPath(); + var pythonExec = fullPath; if (OperatingSystem.IsWindows()) { // TODO FIXME Longer term we really shouldn't be wrapping calls to python in cmd /c python @@ -224,6 +232,11 @@ private static string FindPython() pythonExec = Path.GetFileName(fullPath); } + if (pythonExec == null) + { + return null; + } + var process = ProcessHelpers.RunShellCommandAsync(pythonExec, "--version").Result; if (process.ExitCode == 0 && process.MergedOutput.Contains("Python 3.")) { diff --git a/src/common/details/helpers/try_catch_helpers.cs b/src/common/details/helpers/try_catch_helpers.cs index 0cf9ca97..387ce5e5 100644 --- a/src/common/details/helpers/try_catch_helpers.cs +++ b/src/common/details/helpers/try_catch_helpers.cs @@ -10,22 +10,22 @@ namespace Azure.AI.Details.Common.CLI { public class TryCatchHelpers { - public static Exception TryCatchRetryNoThrow(Action action, int retryTimes = 10) + public static Exception? TryCatchRetryNoThrow(Action action, int retryTimes = 10) { return TryCatchRetryNoThrow(action, null, retryTimes); } - public static Exception TryCatchRetryNoThrow(Action action, Func retryIf, int retryTimes = 10) + public static Exception? TryCatchRetryNoThrow(Action action, Func retryIf, int retryTimes = 10) { return TryCatchRetryNoThrow(action, retryIf, retryTimes); } - public static ExceptionType TryCatchRetryNoThrow(Action action, int retryTimes = 10) where ExceptionType : Exception + public static ExceptionType? TryCatchRetryNoThrow(Action action, int retryTimes = 10) where ExceptionType : Exception { return TryCatchRetryNoThrow(action, null, retryTimes); } - public static ExceptionType TryCatchRetryNoThrow(Action action, Func retryIf = null, int retryTimes = 10) where ExceptionType : Exception + public static ExceptionType? TryCatchRetryNoThrow(Action action, Func? retryIf = null, int retryTimes = 10) where ExceptionType : Exception { var retry = 0; while (retry <= retryTimes) @@ -64,13 +64,13 @@ public static void TryCatchRetry(Action action, int retryTimes = if (ex != null) throw ex; } - public static void TryCatchRetry(Action action, Func retryIf = null, int retryTimes = 10) where ExceptionType : Exception + public static void TryCatchRetry(Action action, Func? retryIf = null, int retryTimes = 10) where ExceptionType : Exception { var ex = TryCatchRetryNoThrow(action, retryIf, retryTimes); if (ex != null) throw ex; } - public static T TryCatchNoThrow(Func function, T defaultResult, out Exception functionThrewException) + public static T TryCatchNoThrow(Func function, T defaultResult, out Exception? functionThrewException) { functionThrewException = null; try diff --git a/src/common/details/helpers/url_helpers.cs b/src/common/details/helpers/url_helpers.cs index ded5b8d4..1a13a7c8 100644 --- a/src/common/details/helpers/url_helpers.cs +++ b/src/common/details/helpers/url_helpers.cs @@ -52,7 +52,7 @@ public static string IdFromString(string value, IdKind kind = IdKind.Guid) public static string GetIdFromNamedValue(ICommandValues values, string name, string defaultValue = "") { var value = values.GetOrDefault(name, defaultValue); - return IdHelpers.IdFromString(value); + return IdHelpers.IdFromString(value!); } public static void CheckWriteOutputNameOrId(string nameOrId, INamedValues values, string domain, IdKind kind) @@ -60,11 +60,11 @@ public static void CheckWriteOutputNameOrId(string nameOrId, INamedValues values var atIdName = kind == IdKind.Name ? $"{domain}.output.name" : $"{domain}.output.id"; - var atId = values.GetOrDefault(atIdName, ""); + var atId = values.GetOrEmpty(atIdName); var atIdOk = !string.IsNullOrEmpty(atId); if (atIdOk) { - var atIdFile = FileHelpers.GetOutputDataFileName(atId, values); + var atIdFile = FileHelpers.GetOutputDataFileName(atId, values)!; FileHelpers.WriteAllText(atIdFile, nameOrId, Encoding.UTF8); values.Reset(atIdName); // once we wrote it, don't try to again } @@ -72,11 +72,11 @@ public static void CheckWriteOutputNameOrId(string nameOrId, INamedValues values var addIdName = kind == IdKind.Name ? $"{domain}.output.add.name" : $"{domain}.output.add.id"; - var addId = values.GetOrDefault(addIdName, ""); + var addId = values.GetOrEmpty(addIdName); var addIdOk = !string.IsNullOrEmpty(addId); if (addIdOk) { - var addIdFile = FileHelpers.GetOutputDataFileName(addId, values); + var addIdFile = FileHelpers.GetOutputDataFileName(addId, values)!; FileHelpers.AppendAllText(addIdFile, "\n" + nameOrId, Encoding.UTF8); values.Reset(addIdName); // once we wrote it, don't try to again } @@ -87,7 +87,10 @@ public static void CheckWriteOutputNameOrId(string json, string nameOrIdName, IN var parsed = JsonDocument.Parse(json); var value = parsed.GetPropertyElementOrNull(nameOrIdName); var nameOrId = value?.GetString(); - CheckWriteOutputNameOrId(nameOrId, values, domain, kind); + if (nameOrId != null) + { + CheckWriteOutputNameOrId(nameOrId, values, domain, kind); + } } #region private data @@ -107,7 +110,7 @@ public static string ContinueWithQueryString(string name, string value) public static string ContinueWithQueryString(string name, INamedValues values, string valueName) { - var value = values.GetOrDefault(valueName, ""); + var value = values.GetOrEmpty(valueName); return ContinueWithQueryString(name, value); } @@ -120,7 +123,7 @@ public static string ContinueWithQueryStringOrEmpty(string name, string value) public static string ContinueWithQueryStringOrEmpty(string name, INamedValues values, string valueName) { - var value = values.GetOrDefault(valueName, ""); + var value = values.GetOrEmpty(valueName); return ContinueWithQueryStringOrEmpty(name, value); } @@ -136,12 +139,12 @@ public static string CheckWriteOutputUrlOrId(string url, INamedValues values, st return url; } - public static string CheckWriteOutputUrlOrId(string json, string urlName, INamedValues values, string domain, IdKind kinds = IdKind.Guid) + public static string? CheckWriteOutputUrlOrId(string json, string urlName, INamedValues values, string domain, IdKind kinds = IdKind.Guid) { var parsed = JsonDocument.Parse(json); var value = parsed?.GetPropertyElementOrNull(urlName); var url = value?.GetString(); - return CheckWriteOutputUrlOrId(url, values, domain, kinds); + return url != null ? CheckWriteOutputUrlOrId(url!, values, domain, kinds) : null; } public static void CheckWriteOutputUrlsOrIds(string json, string arrayName, string urlName, INamedValues values, string domain, IdKind kinds = IdKind.Guid) @@ -155,25 +158,25 @@ public static void CheckWriteOutputUrlsOrIds(string json, string arrayName, stri public static void CheckWriteOutputUrlsOrIds(INamedValues values, string domain, List urls, List ids, IdKind kind) { var atUrlsName = $"{domain}.output.urls"; - var atUrls = values.GetOrDefault(atUrlsName, ""); + var atUrls = values.GetOrEmpty(atUrlsName); var atUrlsOk = !string.IsNullOrEmpty(atUrls); var atIdsName = kind == IdKind.Name ? $"{domain}.output.names" : $"{domain}.output.ids"; - var atIds = values.GetOrDefault(atIdsName, ""); + var atIds = values.GetOrEmpty(atIdsName); var atIdsOk = !string.IsNullOrEmpty(atIds); if (atUrlsOk) { - var atUrlsFile = FileHelpers.GetOutputDataFileName(atUrls, values); + var atUrlsFile = FileHelpers.GetOutputDataFileName(atUrls, values)!; FileHelpers.WriteAllLines(atUrlsFile, urls, new UTF8Encoding(false)); values.Reset(atUrlsName); // only write once } if (atIdsOk) { - var atIdsFile = FileHelpers.GetOutputDataFileName(atIds, values); + var atIdsFile = FileHelpers.GetOutputDataFileName(atIds, values)!; FileHelpers.WriteAllLines(atIdsFile, ids, new UTF8Encoding(false)); values.Reset(atIdsName); } @@ -194,21 +197,21 @@ private static void CheckWriteOutputUrl(string url, INamedValues values, string if (!urlOk) return; var atUrlName = $"{domain}.output.url"; - var atUrl = values.GetOrDefault(atUrlName, ""); + var atUrl = values.GetOrEmpty(atUrlName); var atUrlOk = !string.IsNullOrEmpty(atUrl); if (atUrlOk) { - var atUrlFile = FileHelpers.GetOutputDataFileName(atUrl, values); + var atUrlFile = FileHelpers.GetOutputDataFileName(atUrl, values)!; FileHelpers.WriteAllText(atUrlFile, url, Encoding.UTF8); values.Reset(atUrlName); // once we wrote it, don't try to again } var addUrlName = $"{domain}.output.add.url"; - var addUrl = values.GetOrDefault(addUrlName, ""); + var addUrl = values.GetOrEmpty(addUrlName); var addUrlOk = !string.IsNullOrEmpty(addUrl); if (addUrlOk) { - var addUrlFile = FileHelpers.GetOutputDataFileName(addUrl, values); + var addUrlFile = FileHelpers.GetOutputDataFileName(addUrl, values)!; FileHelpers.AppendAllText(addUrlFile, "\n" + url, Encoding.UTF8); values.Reset(addUrlName); // once we wrote it, don't try to again } @@ -240,7 +243,7 @@ public static void GetUrlsOrIds(string json, string arrayName, string urlName, I var askedForThisKind = (thisKind & kinds) != 0; if (askedForThisKind) { - GetUrlsAndIdsForOneKind(json, arrayName, urlName, getUrlsOnlyOnce, ids, thisKind); + GetUrlsAndIdsForOneKind(json, arrayName, urlName, getUrlsOnlyOnce!, ids, thisKind); getUrlsOnlyOnce = null; // we'll get the URLs on the first } } diff --git a/src/common/details/named_values/environment_named_values.cs b/src/common/details/named_values/environment_named_values.cs index ebf17064..dd1b3d75 100644 --- a/src/common/details/named_values/environment_named_values.cs +++ b/src/common/details/named_values/environment_named_values.cs @@ -20,21 +20,23 @@ public EnvironmentNamedValues() var vars = Environment.GetEnvironmentVariables(); foreach (var key in vars.Keys) { - if (key.ToString().ToLower().StartsWith($"{Program.Name}_")) + var ks = key.ToString() ?? string.Empty; + var nameAndPrefix = $"{Program.Name}_"; + if (ks.ToLower().StartsWith(nameAndPrefix)) { - var name = key.ToString().Substring(4).Replace("_", ".").ToLower(); - var value = vars[key].ToString(); + var name = ks.Substring(nameAndPrefix.Length).Replace("_", ".").ToLower(); + var value = vars[key]!.ToString(); _values.Add(name, value); } } } - public string this[string name] => Get(name, true); + public string? this[string name] => Get(name, true); public IEnumerable Names => _values.Names; - public void Add(string name, string value) => _values.Add(name, value); + public void Add(string name, string? value) => _values.Add(name, value); public bool Contains(string name, bool checkDefault = true) => _values.Contains(name, checkDefault); - public string Get(string name, bool checkDefault = true) => _values.Get(name, checkDefault); - public void Reset(string name, string value = null) => _values.Reset(name, value); + public string? Get(string name, bool checkDefault = true) => _values.Get(name, checkDefault); + public void Reset(string name, string? value = null) => _values.Reset(name, value); private INamedValues _values; } diff --git a/src/common/details/named_values/named_value_tokens.cs b/src/common/details/named_values/named_value_tokens.cs index 64d755d9..b8c3f395 100644 --- a/src/common/details/named_values/named_value_tokens.cs +++ b/src/common/details/named_values/named_value_tokens.cs @@ -7,17 +7,17 @@ namespace Azure.AI.Details.Common.CLI { public abstract class INamedValueTokens { - public abstract string PopNextToken(); - public abstract string PopNextTokenValue(INamedValues values = null); + public abstract string? PopNextToken(); + public abstract string? PopNextTokenValue(INamedValues? values = null); - public abstract string PeekNextToken(int skip = 0); - public abstract string PeekNextTokenValue(int skip = 0, INamedValues values = null); + public abstract string? PeekNextToken(int skip = 0); + public abstract string? PeekNextTokenValue(int skip = 0, INamedValues? values = null); public abstract string PeekAllTokens(int count = int.MaxValue); public abstract void SkipTokens(int count); - public abstract string ValueFromToken(string token, INamedValues values = null); + public abstract string? ValueFromToken(string? token, INamedValues? values = null); public abstract string NamePrefixRequired(); } diff --git a/src/common/details/named_values/named_values.cs b/src/common/details/named_values/named_values.cs index 7cb7542d..008687e6 100644 --- a/src/common/details/named_values/named_values.cs +++ b/src/common/details/named_values/named_values.cs @@ -15,19 +15,24 @@ namespace Azure.AI.Details.Common.CLI { public interface INamedValues { - void Add(string name, string value); + void Add(string name, string? value); bool Contains(string name, bool checkDefault = true); - string Get(string name, bool checkDefault = true); + string? Get(string name, bool checkDefault = true); - void Reset(string name, string value = null); + void Reset(string name, string? value = null); - string this[string name] { get; } + string? this[string name] { get; } IEnumerable Names { get; } } public static class NamedValueExtensions { - public static string GetOrDefault(this INamedValues values, string name, string defaultValue) + public static string GetOrEmpty(this INamedValues values, string name) + { + return values.GetOrDefault(name, string.Empty)!; + } + + public static string? GetOrDefault(this INamedValues values, string name, string? defaultValue) { var value = values[name]; return !string.IsNullOrEmpty(value) ? value : defaultValue; @@ -65,22 +70,23 @@ public static TVal GetOrAdd(this INamedValues values, string name, Func(this T values) where T : INamedValues { foreach (var name in values.Names) { - var value0 = values[name]; + var value0 = values[name]!; var value1 = value0.ReplaceValues(values); if (value0 != value1) { @@ -116,24 +122,24 @@ public static T ReplaceValues(this T values) where T : INamedValues return values; } - public static string SaveAs(this INamedValues values, string fileName = null) + public static string SaveAs(this INamedValues values, string? fileName = null) { return values.SaveAs(values.Names, fileName); } - public static string SaveAs(this INamedValues values, IEnumerable names, string fileName = null) + public static string SaveAs(this INamedValues values, IEnumerable names, string? fileName = null) { fileName = fileName == null ? Path.GetTempFileName() : FileHelpers.GetOutputDataFileName(fileName, values); - string allFileNames = fileName; + string allFileNames = fileName!; List lines = new List(); foreach (var name in names) { var value = values[name]; - if (value.Contains('\n') || value.Contains('\t')) + if (value != null && (value.Contains('\n') || value.Contains('\t'))) { var additionalFile = fileName + "." + name; FileHelpers.WriteAllText(additionalFile, value, Encoding.UTF8); @@ -146,7 +152,7 @@ public static string SaveAs(this INamedValues values, IEnumerable names, } } - FileHelpers.WriteAllLines(fileName, lines, new UTF8Encoding(false)); + FileHelpers.WriteAllLines(fileName!, lines, new UTF8Encoding(false)); return allFileNames; } @@ -208,25 +214,25 @@ public static bool DumpHelpRequested(this INamedValues values) return values.GetOrDefault("display.help.dump", false); } - public static string GetCommand(this INamedValues values, string defaultValue = "") + public static string? GetCommand(this INamedValues values, string defaultValue = "") { return values.GetOrDefault("x.command", defaultValue); } - public static string GetCommandRoot(this INamedValues values, string defaultValue = "") + public static string? GetCommandRoot(this INamedValues values, string defaultValue = "") { - return values.GetCommand(defaultValue).Split('.').FirstOrDefault(); + return values.GetCommand(defaultValue)?.Split('.').FirstOrDefault() ?? string.Empty; } - public static string GetCommandForDisplay(this INamedValues values) + public static string? GetCommandForDisplay(this INamedValues values) { - return values.GetCommand().Replace('.', ' '); + return values.GetCommand()?.Replace('.', ' '); } } public class NamedValues : INamedValues { - public void Add(string name, string value) + public void Add(string name, string? value) { var exists = _values.ContainsKey(name); var current = exists ? _values[name] : null; @@ -246,12 +252,12 @@ public bool Contains(string name, bool checkDefault = true) return _values.ContainsKey(name); } - public string Get(string name, bool checkDefault = true) + public string? Get(string name, bool checkDefault = true) { return Contains(name, checkDefault) ? _values[name] : null; } - public void Reset(string name, string value = null) + public void Reset(string name, string? value = null) { _values.Remove(name); _names.Remove(name); @@ -261,7 +267,7 @@ public void Reset(string name, string value = null) } } - public string this[string name] + public string? this[string name] { get { @@ -277,7 +283,7 @@ public IEnumerable Names } } - private Dictionary _values = new Dictionary(); + private Dictionary _values = new Dictionary(); private List _names = new List(); } } diff --git a/src/common/details/named_values/parsers/for_each_token_parser.cs b/src/common/details/named_values/parsers/for_each_token_parser.cs index 0d6e00af..fca4134b 100644 --- a/src/common/details/named_values/parsers/for_each_token_parser.cs +++ b/src/common/details/named_values/parsers/for_each_token_parser.cs @@ -35,7 +35,7 @@ public override bool Parse(INamedValueTokens tokens, INamedValues values) { return ParseIndexedTsvFile(tokens, values, index); } - else if (token.Where(x => char.IsDigit(x)).Count() == token.Length) + else if (token != null && token.Where(x => char.IsDigit(x)).Count() == token.Length) { return ParseIndexedTsvFile(tokens, values, int.Parse(token)); } @@ -122,7 +122,7 @@ private static bool ParseIndexedTsvFile(INamedValueTokens tokens, INamedValues v return false; } - private static bool ParseNonIndexedTsvFile(INamedValueTokens tokens, INamedValues values, string token, int skip, int index) + private static bool ParseNonIndexedTsvFile(INamedValueTokens tokens, INamedValues values, string? token, int skip, int index) { // --foreach [tsv] @COL-TSV-FILE [skip header] in @TSV-FILE // --foreach [tsv] [columns] "COL1;COL2" [skip header] in @TSV-FILE @@ -149,6 +149,8 @@ private static bool ParseNonIndexedTsvFile(INamedValueTokens tokens, INamedValue token = tokens.PeekNextToken(skip++); } + if (token == null) return false; + var hasHeader = string.IsNullOrEmpty(columns) || skipHeader; var atFile = token.StartsWith("@"); @@ -158,7 +160,7 @@ private static bool ParseNonIndexedTsvFile(INamedValueTokens tokens, INamedValue { var value = isFile ? FileHelpers.ReadAllText(token, Encoding.Default) - : tokens.ValueFromToken(token); + : tokens.ValueFromToken(token)!; if (isList) { hasHeader = false; diff --git a/src/common/details/named_values/parsers/input_wildcard_token_parser.cs b/src/common/details/named_values/parsers/input_wildcard_token_parser.cs index c788ec7c..7eb9a4ee 100644 --- a/src/common/details/named_values/parsers/input_wildcard_token_parser.cs +++ b/src/common/details/named_values/parsers/input_wildcard_token_parser.cs @@ -38,7 +38,7 @@ private bool ParseValues(INamedValueTokens tokens, INamedValues values, int name if (peekToken1 != null && peekToken1.Contains('=')) { - StringHelpers.SplitNameValue(peekToken1Value, out var name, out var value); + StringHelpers.SplitNameValue(peekToken1Value!, out var name, out var value); values.Add("input." + name, value); tokens.SkipTokens(nameTokenCount + 1); return true; diff --git a/src/common/details/named_values/parsers/named_value_token_parser.cs b/src/common/details/named_values/parsers/named_value_token_parser.cs index 87fa32b0..d2fcfce8 100644 --- a/src/common/details/named_values/parsers/named_value_token_parser.cs +++ b/src/common/details/named_values/parsers/named_value_token_parser.cs @@ -27,9 +27,9 @@ public class NamedValueTokenParser : INamedValueTokenParser /// The default value, unless pinnedValueKey is non-null, then the value passed to a property with the name whose value is pinnedValueKey /// The name of the property value pinnedValue will be set to. public NamedValueTokenParser( - string name, string fullName, string requiredParts, - string valueCount, string validValues = null, string valueKey = null, - string pinnedValue = null, string pinnedValueKey = null) + string? name, string fullName, string requiredParts, + string valueCount, string? validValues = null, string? valueKey = null, + string? pinnedValue = null, string? pinnedValueKey = null) { ShortName = name; FullName = fullName; @@ -128,12 +128,12 @@ private bool ParseValues(INamedValueTokens tokens, INamedValues values, int coun else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, true)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)); + parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)!); } else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, false)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextToken().TrimStart('=')); + parsed = AddValue(values, ValueKey, tokens.PopNextToken()!.TrimStart('=')); } else if (count == 2 && ValueMatchesValidValue(peekToken1, peekToken1Value) && peekToken2Value != null) { @@ -155,12 +155,12 @@ private bool ParseValues(INamedValueTokens tokens, INamedValues values, int coun else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, true)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)); + parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)!); } else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, false)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextToken().TrimStart('=')); + parsed = AddValue(values, ValueKey, tokens.PopNextToken()!.TrimStart('=')); } } else // if (PinnedValueKey != null && PinnedValue != null) @@ -168,21 +168,21 @@ private bool ParseValues(INamedValueTokens tokens, INamedValues values, int coun if (count == 0) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, PinnedValueKey, PinnedValue); + parsed = AddValue(values, PinnedValueKey!, PinnedValue!); } else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, true)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)); - parsed = parsed && AddValue(values, PinnedValueKey, PinnedValue); + parsed = AddValue(values, ValueKey, tokens.PopNextTokenValue(values)!); + parsed = parsed && AddValue(values, PinnedValueKey!, PinnedValue!); } else if (count == 1 && ValueMatchesValidValue(peekToken1, peekToken1Value, false)) { tokens.SkipTokens(skipNameTokens); - parsed = AddValue(values, ValueKey, tokens.PopNextToken().TrimStart('=')); - parsed = parsed && AddValue(values, PinnedValueKey, PinnedValue); + parsed = AddValue(values, ValueKey, tokens.PopNextToken()!.TrimStart('=')); + parsed = parsed && AddValue(values, PinnedValueKey!, PinnedValue!); } else if (count == 2 && ValueMatchesValidValue(peekToken1, peekToken1Value) && peekToken2Value != null) { @@ -192,14 +192,14 @@ private bool ParseValues(INamedValueTokens tokens, INamedValues values, int coun value += "=" + tokens.PopNextTokenValue(values); parsed = AddValue(values, ValueKey, value.TrimStart('=')); - parsed = parsed && AddValue(values, PinnedValueKey, PinnedValue); + parsed = parsed && AddValue(values, PinnedValueKey!, PinnedValue!); } } return parsed; } - private bool ValueMatchesValidValue(string peekToken, string peekTokenValue, bool skipAtAt = false) + private bool ValueMatchesValidValue(string? peekToken, string? peekTokenValue, bool skipAtAt = false) { return NamedValueTokenParserHelpers.ValueMatchesValidValue(ValidValues, peekToken, peekTokenValue, skipAtAt); } @@ -278,16 +278,16 @@ private bool AddValue(INamedValues values, string key, string value) #region protected / private data - protected string ShortName; // e.g. "--file" + protected string? ShortName; // e.g. "--file" protected string FullName; // e.g. "audio.input.push.stream.file" protected string RequiredParts; // e.g. "00100" protected string ValueCount; // e.g. "0" or "1" or "2" or "2;1" or ... - protected string ValidValues; // e.g. "file;blob;microphone" + protected string? ValidValues; // e.g. "file;blob;microphone" protected string ValueKey; // e.g. "audio.input.type" - protected string PinnedValue; - protected string PinnedValueKey; + protected string? PinnedValue; + protected string? PinnedValueKey; #endregion } diff --git a/src/common/details/named_values/parsers/named_value_token_parser_helpers.cs b/src/common/details/named_values/parsers/named_value_token_parser_helpers.cs index 56f4dab3..21914c21 100644 --- a/src/common/details/named_values/parsers/named_value_token_parser_helpers.cs +++ b/src/common/details/named_values/parsers/named_value_token_parser_helpers.cs @@ -7,7 +7,7 @@ namespace Azure.AI.Details.Common.CLI { public class NamedValueTokenParserHelpers { - public static bool MatchShortName(string shortName, INamedValueTokens tokens, INamedValues values, out int nameTokenCount) + public static bool MatchShortName(string? shortName, INamedValueTokens tokens, INamedValues values, out int nameTokenCount) { nameTokenCount = 0; @@ -85,7 +85,7 @@ public static bool MatchFullName(string fullName, INamedValueTokens tokens, INam return false; } - public static bool ValueMatchesValidValue(string validValues, string peekToken, string peekTokenValue, bool skipAtAt = false) + public static bool ValueMatchesValidValue(string? validValues, string? peekToken, string? peekTokenValue, bool skipAtAt = false) { if (peekToken == null) return false; if (peekTokenValue == null) return false; @@ -117,7 +117,7 @@ public static bool ValueMatchesValidValue(string validValues, string peekToken, return false; } - private static void SetWild(INamedValues values, string fullNamePart, string tokenPart) + private static void SetWild(INamedValues values, string fullNamePart, string? tokenPart) { values.Reset(fullNamePart); values.Add(fullNamePart, tokenPart); diff --git a/src/common/details/named_values/parsers/option_x_token_parser.cs b/src/common/details/named_values/parsers/option_x_token_parser.cs index 0023332b..4a14447a 100644 --- a/src/common/details/named_values/parsers/option_x_token_parser.cs +++ b/src/common/details/named_values/parsers/option_x_token_parser.cs @@ -47,7 +47,7 @@ private bool ParseValuesUntilNextTokenPrefixed(INamedValueTokens tokens, INamedV if (peekToken.StartsWith(prefix)) break; var peekTokenValue = tokens.ValueFromToken(peekToken, values); - queue.Enqueue(peekTokenValue); + queue.Enqueue(peekTokenValue!); iPeekToken++; } diff --git a/src/common/details/named_values/parsers/replace_for_each_token_parser.cs b/src/common/details/named_values/parsers/replace_for_each_token_parser.cs index 18f80b33..c0308765 100644 --- a/src/common/details/named_values/parsers/replace_for_each_token_parser.cs +++ b/src/common/details/named_values/parsers/replace_for_each_token_parser.cs @@ -40,8 +40,8 @@ public override bool Parse(INamedValueTokens tokens, INamedValues values) var token5 = tokens.PeekNextToken(skip++); var delegateTokens = token4 == "files" && !string.IsNullOrEmpty(token5) - ? ParseReplaceForEachInFiles(tokens, values, name, skip -= 1) - : ParseReplaceForEachInSemiListOrAtFile(tokens, values, name, skip -= 2); + ? ParseReplaceForEachInFiles(tokens, values, name!, skip -= 1) + : ParseReplaceForEachInSemiListOrAtFile(tokens, values, name!, skip -= 2); var forEachTokenSource = new CmdLineTokenSource(delegateTokens.ToArray(), values); var parsed = _forEachTokenParser.Parse(forEachTokenSource, values); @@ -55,7 +55,7 @@ private IEnumerable ParseReplaceForEachInFiles(INamedValueTokens tokens, yield return $"replace.var.{name}"; yield return "in"; - var pattern = tokens.PeekNextToken(skip); + var pattern = tokens.PeekNextToken(skip)!; var found = FileHelpers.FindFiles(pattern, values).ToList(); var str = string.Join(";", found); @@ -67,7 +67,7 @@ private IEnumerable ParseReplaceForEachInSemiListOrAtFile(INamedValueTok yield return "--foreach"; yield return $"replace.var.{name}"; yield return "in"; - yield return tokens.PeekNextToken(v); + yield return tokens.PeekNextToken(v)!; } private NamedValueTokenParser _parser1 = new NamedValueTokenParser(null, "replace.var.*", "011;101", "1;0", null, null, "="); diff --git a/src/common/details/named_values/sources/cmd_line_token_source.cs b/src/common/details/named_values/sources/cmd_line_token_source.cs index ebaeba3e..f1658196 100644 --- a/src/common/details/named_values/sources/cmd_line_token_source.cs +++ b/src/common/details/named_values/sources/cmd_line_token_source.cs @@ -87,7 +87,7 @@ public CmdLineTokenSource(string[] tokens, INamedValues values) } } - public override string PopNextToken() + public override string? PopNextToken() { if (_tokens.Count == 0) return null; @@ -97,18 +97,18 @@ public override string PopNextToken() return token; } - public override string PopNextTokenValue(INamedValues values = null) + public override string? PopNextTokenValue(INamedValues? values = null) { var token = PopNextToken(); return ValueFromToken(token, values); } - public override string PeekNextToken(int skip = 0) + public override string? PeekNextToken(int skip = 0) { return _tokens.Count > skip ? _tokens[skip] : null; } - public override string PeekNextTokenValue(int skip = 0, INamedValues values = null) + public override string? PeekNextTokenValue(int skip = 0, INamedValues? values = null) { var token = PeekNextToken(skip); return ValueFromToken(token, values); @@ -131,7 +131,7 @@ public override void SkipTokens(int count) _tokens.RemoveRange(0, Math.Min(count, _tokens.Count)); } - public override string ValueFromToken(string token, INamedValues values = null) + public override string? ValueFromToken(string? token, INamedValues? values = null) { if (token == null) return null; diff --git a/src/common/details/named_values/sources/ini_line_token_source.cs b/src/common/details/named_values/sources/ini_line_token_source.cs index 416e9f81..12d8e3a7 100644 --- a/src/common/details/named_values/sources/ini_line_token_source.cs +++ b/src/common/details/named_values/sources/ini_line_token_source.cs @@ -39,7 +39,7 @@ public IniLineTokenSource(string line) } } - public override string PopNextToken() + public override string? PopNextToken() { if (_tokens.Count == 0) return null; @@ -49,18 +49,18 @@ public override string PopNextToken() return token; } - public override string PopNextTokenValue(INamedValues values = null) + public override string? PopNextTokenValue(INamedValues? values = null) { var token = PopNextToken(); return ValueFromToken(token, values); } - public override string PeekNextToken(int skip = 0) + public override string? PeekNextToken(int skip = 0) { return _tokens.Count > skip ? _tokens[skip] : null; } - public override string PeekNextTokenValue(int skip = 0, INamedValues values = null) + public override string? PeekNextTokenValue(int skip = 0, INamedValues? values = null) { var token = PeekNextToken(skip); return ValueFromToken(token, values); @@ -83,7 +83,7 @@ public override void SkipTokens(int count) _tokens.RemoveRange(0, Math.Min(count, _tokens.Count)); } - public override string ValueFromToken(string token, INamedValues values = null) + public override string? ValueFromToken(string? token, INamedValues? values = null) { if (token == null || !token.StartsWith("=")) return null; return FileHelpers.ExpandAtFileValue(token.Substring(1), values); diff --git a/src/common/details/named_values/sources/tsv_row_token_source.cs b/src/common/details/named_values/sources/tsv_row_token_source.cs index df568d55..986fd049 100644 --- a/src/common/details/named_values/sources/tsv_row_token_source.cs +++ b/src/common/details/named_values/sources/tsv_row_token_source.cs @@ -32,7 +32,7 @@ public TsvRowTokenSource(string columnNames, string rowValues) } } - public override string PopNextToken() + public override string? PopNextToken() { if (_tokens.Count == 0) return null; @@ -42,18 +42,18 @@ public override string PopNextToken() return token; } - public override string PopNextTokenValue(INamedValues values = null) + public override string? PopNextTokenValue(INamedValues? values = null) { var token = PopNextToken(); return ValueFromToken(token, values); } - public override string PeekNextToken(int skip = 0) + public override string? PeekNextToken(int skip = 0) { return _tokens.Count > skip ? _tokens[skip] : null; } - public override string PeekNextTokenValue(int skip = 0, INamedValues values = null) + public override string? PeekNextTokenValue(int skip = 0, INamedValues? values = null) { var token = PeekNextToken(skip); return ValueFromToken(token, values); @@ -79,7 +79,7 @@ public override void SkipTokens(int count) _tokens.RemoveRange(0, Math.Min(count, _tokens.Count)); } - public override string ValueFromToken(string token, INamedValues values = null) + public override string? ValueFromToken(string? token, INamedValues? values = null) { if (token == null) return null; return token.StartsWith("=") ? token.Substring(1) : null; diff --git a/src/common/details/named_values/tokens/arg_x_token.cs b/src/common/details/named_values/tokens/arg_x_token.cs index d0c828fa..c12eb453 100644 --- a/src/common/details/named_values/tokens/arg_x_token.cs +++ b/src/common/details/named_values/tokens/arg_x_token.cs @@ -9,7 +9,7 @@ public class ArgXToken { public static INamedValueTokenParser Parser() => new ArgXTokenParser(); - public static string GetArg(ICommandValues values, int x) => values.GetOrDefault("arg" + x, null); + public static string? GetArg(ICommandValues values, int x) => values.GetOrDefault("arg" + x, null); public static IEnumerable GetArgs(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/conatins_option_x_token.cs b/src/common/details/named_values/tokens/conatins_option_x_token.cs index 34629d05..8857a6fd 100644 --- a/src/common/details/named_values/tokens/conatins_option_x_token.cs +++ b/src/common/details/named_values/tokens/conatins_option_x_token.cs @@ -9,7 +9,7 @@ public class ContainsOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/file_option_x_token.cs b/src/common/details/named_values/tokens/file_option_x_token.cs index 35ea998f..14ced49d 100644 --- a/src/common/details/named_values/tokens/file_option_x_token.cs +++ b/src/common/details/named_values/tokens/file_option_x_token.cs @@ -9,7 +9,7 @@ public class FileOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/files_option_x_token.cs b/src/common/details/named_values/tokens/files_option_x_token.cs index 1dafbb62..a17e340b 100644 --- a/src/common/details/named_values/tokens/files_option_x_token.cs +++ b/src/common/details/named_values/tokens/files_option_x_token.cs @@ -9,7 +9,7 @@ public class FilesOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/named_value_token_data.cs b/src/common/details/named_values/tokens/named_value_token_data.cs index ce70b8a3..30c5688f 100644 --- a/src/common/details/named_values/tokens/named_value_token_data.cs +++ b/src/common/details/named_values/tokens/named_value_token_data.cs @@ -17,7 +17,7 @@ public NamedValueTokenData(string optionName, string fullName, string optionExam _requiredDisplayName = requiredDisplayName; } - public string Demand(INamedValues values, string action, string command, string checkConfig = null) + public string Demand(INamedValues values, string action, string command, string? checkConfig = null) { if (checkConfig != null) { @@ -35,7 +35,7 @@ public string Demand(INamedValues values, string action, string command, string return NamedValueTokenDataHelpers.Demand(values, _fullName, _requiredDisplayName, $"{_optionName} {_optionExample}", action, command); } - public string GetOrDefault(INamedValues values, string defaultValue = null) + public string? GetOrDefault(INamedValues values, string? defaultValue = null) { return values.GetOrDefault(_fullName, defaultValue); } @@ -50,12 +50,12 @@ public int GetOrDefault(INamedValues values, int defaultValue) return values.GetOrDefault(_fullName, defaultValue); } - public void Set(INamedValues values, string value = null) + public void Set(INamedValues values, string? value = null) { values.Reset(_fullName, value); } - private string ReadConfig(INamedValues values, string name) + private string? ReadConfig(INamedValues values, string name) { return FileHelpers.FileExistsInConfigPath(name, values) ? FileHelpers.ReadAllText(FileHelpers.DemandFindFileInConfigPath(name, values, "configuration"), Encoding.UTF8) diff --git a/src/common/details/named_values/tokens/named_value_token_data_helpers.cs b/src/common/details/named_values/tokens/named_value_token_data_helpers.cs index 6a9e3c34..762290a6 100644 --- a/src/common/details/named_values/tokens/named_value_token_data_helpers.cs +++ b/src/common/details/named_values/tokens/named_value_token_data_helpers.cs @@ -17,7 +17,7 @@ public static string Demand(INamedValues values, string valueName, string requir "TRY:", $"{Program.Name} {command} {option}", "SEE:", $"{Program.Name} help {command}"); } - return value; + return value!; } } } diff --git a/src/common/details/named_values/tokens/remove_option_x_token.cs b/src/common/details/named_values/tokens/remove_option_x_token.cs index dfc63449..42024bf5 100644 --- a/src/common/details/named_values/tokens/remove_option_x_token.cs +++ b/src/common/details/named_values/tokens/remove_option_x_token.cs @@ -9,7 +9,7 @@ public class RemoveOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/search_option_x_token.cs b/src/common/details/named_values/tokens/search_option_x_token.cs index 1c13917e..e716bef8 100644 --- a/src/common/details/named_values/tokens/search_option_x_token.cs +++ b/src/common/details/named_values/tokens/search_option_x_token.cs @@ -9,7 +9,7 @@ public class SearchOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/test_option_x_token.cs b/src/common/details/named_values/tokens/test_option_x_token.cs index 3cbb359c..650d6896 100644 --- a/src/common/details/named_values/tokens/test_option_x_token.cs +++ b/src/common/details/named_values/tokens/test_option_x_token.cs @@ -9,7 +9,7 @@ public class TestOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/common/details/named_values/tokens/tests_option_x_token.cs b/src/common/details/named_values/tokens/tests_option_x_token.cs index 12f52e46..993f7f1c 100644 --- a/src/common/details/named_values/tokens/tests_option_x_token.cs +++ b/src/common/details/named_values/tokens/tests_option_x_token.cs @@ -9,7 +9,7 @@ public class TestsOptionXToken { public static INamedValueTokenParser Parser() => new OptionXTokenParser(_optionName, _fullName, "1"); - public static string GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); + public static string? GetOption(ICommandValues values, int x) => values.GetOrDefault($"{_fullName}.{x}", null); public static IEnumerable GetOptions(ICommandValues values) { diff --git a/src/extensions/speech_extension/commands/base/recognize_commands_base.cs b/src/extensions/speech_extension/commands/base/recognize_commands_base.cs index 992f05b3..dbb37848 100644 --- a/src/extensions/speech_extension/commands/base/recognize_commands_base.cs +++ b/src/extensions/speech_extension/commands/base/recognize_commands_base.cs @@ -15,6 +15,10 @@ namespace Azure.AI.Details.Common.CLI { public class RecognizeCommandBase : Command { + internal RecognizeCommandBase(ICommandValues values) : base(values) + { + } + protected void StartCommand() { CheckPath(); @@ -23,15 +27,15 @@ protected void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -43,15 +47,15 @@ protected void StartCommand() protected void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } protected KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -103,44 +107,44 @@ protected void WaitForOnceStopCancelOrKey(DialogServiceConnector connector, Task } #region Event Handlers - protected void SessionStarted(object sender, SessionEventArgs e) + protected void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - protected void SessionStopped(object sender, SessionEventArgs e) + protected void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - protected void Recognizing(object sender, SpeechRecognitionEventArgs e) + protected void Recognizing(object? sender, SpeechRecognitionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayRecognizing(e); - _output.Recognizing(e); + _display!.DisplayRecognizing(e); + _output!.Recognizing(e); } - protected void Recognized(object sender, SpeechRecognitionEventArgs e) + protected void Recognized(object? sender, SpeechRecognitionEventArgs e) { - _display.DisplayRecognized(e); - _output.Recognized(e); + _display!.DisplayRecognized(e); + _output!.Recognized(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - protected void Canceled(object sender, SpeechRecognitionCanceledEventArgs e) + protected void Canceled(object? sender, SpeechRecognitionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } #endregion @@ -182,7 +186,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -203,7 +207,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -228,9 +232,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -244,10 +247,11 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } + #endregion #region private backing methods @@ -285,12 +289,12 @@ private void WaitForKeywordCancelKeyOrTimeoutInternal(ManualResetEvent canceledE protected bool _connect = false; protected bool _disconnect = false; - protected SpinLock _lock = null; + protected SpinLock? _lock = null; protected int _expectRecognized = 0; protected int _expectSessionStopped = 0; protected int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/batch_command.cs b/src/extensions/speech_extension/commands/batch_command.cs index 76bf9c03..0f4a56f5 100644 --- a/src/extensions/speech_extension/commands/batch_command.cs +++ b/src/extensions/speech_extension/commands/batch_command.cs @@ -22,9 +22,8 @@ namespace Azure.AI.Details.Common.CLI { public class BatchCommand : Command { - public BatchCommand(ICommandValues values) + public BatchCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -100,7 +99,7 @@ private void DoOnPremTranscriptionList() batchPaths.AppendLine(batchPath); } - var output = _values.GetOrDefault("batch.transcription.onprem.outfile", ""); + var output = _values.GetOrEmpty("batch.transcription.onprem.outfile"); if (!string.IsNullOrEmpty(output)) { var batchPathsFile = FileHelpers.GetOutputDataFileName(output, _values); @@ -113,7 +112,7 @@ private void DoDeleteOnPremTranscription() { RunOnPremBatchkitIdempotent(); - var id = _values.GetOrDefault("batch.transcription.onprem.id", ""); + var id = _values.GetOrEmpty("batch.transcription.onprem.id"); var message = $"Deleting onprem transcription batch '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -137,7 +136,7 @@ private void DoOnPremTranscriptionStatus() { RunOnPremBatchkitIdempotent(); - string id = _values.GetOrDefault("batch.transcription.onprem.id", ""); + string id = _values.GetOrEmpty("batch.transcription.onprem.id"); int waitTimeout = _values.GetOrDefault("batch.transcription.onprem.status.waitms", 0); var message = waitTimeout <= 0 ? @@ -167,7 +166,7 @@ private void DoOnPremTranscriptionStatus() var json = ReadWritePrintJson(response); - var output = _values.GetOrDefault("batch.transcription.onprem.outfile", ""); + var output = _values.GetOrEmpty("batch.transcription.onprem.outfile"); if (!string.IsNullOrEmpty(output)) { var statusFile = FileHelpers.GetOutputDataFileName(output, _values); @@ -184,16 +183,16 @@ private void DoCreateOnPremTranscription() var batchSpec = new Dictionary(); batchSpec["type"] = "SpeechSDKBatchRequest"; - var filepaths = _values.GetOrDefault("batch.transcription.onprem.create.files", ""); + var filepaths = _values.GetOrEmpty("batch.transcription.onprem.create.files"); batchSpec["files"] = filepaths.Split(",;\r\n".ToCharArray()).ToList(); - batchSpec["language"] = _values.GetOrDefault("batch.transcription.onprem.create.language", "en-US"); - batchSpec["diarization"] = _values.GetOrDefault("batch.transcription.onprem.create.diarization", "None"); - batchSpec["nbest"] = Int32.Parse(_values.GetOrDefault("batch.transcription.onprem.create.nbest", "1")); - batchSpec["profanity"] = _values.GetOrDefault("batch.transcription.onprem.create.profanity", "Masked"); - batchSpec["allow_resume"] = _values.GetOrDefault("batch.transcription.onprem.create.resume", "true"); + batchSpec["language"] = _values.GetOrDefault("batch.transcription.onprem.create.language", "en-US")!; + batchSpec["diarization"] = _values.GetOrDefault("batch.transcription.onprem.create.diarization", "None")!; + batchSpec["nbest"] = Int32.Parse(_values.GetOrDefault("batch.transcription.onprem.create.nbest", "1")!); + batchSpec["profanity"] = _values.GetOrDefault("batch.transcription.onprem.create.profanity", "Masked")!; + batchSpec["allow_resume"] = _values.GetOrDefault("batch.transcription.onprem.create.resume", "true")!; if ((string)batchSpec["allow_resume"] == "") { batchSpec["allow_resume"] = "true"; } - batchSpec["combine_results"] = _values.GetOrDefault("batch.transcription.onprem.create.combine", "false"); + batchSpec["combine_results"] = _values.GetOrDefault("batch.transcription.onprem.create.combine", "false")!; if ((string)batchSpec["combine_results"] == "") { batchSpec["combine_results"] = "true"; } batchSpec["sentiment"] = "false"; @@ -213,7 +212,7 @@ private void DoCreateOnPremTranscription() var json = ReadWritePrintJson(response); - var output = _values.GetOrDefault("batch.transcription.onprem.outfile", ""); + var output = _values.GetOrEmpty("batch.transcription.onprem.outfile"); if (!string.IsNullOrEmpty(output)) { var statusFile = FileHelpers.GetOutputDataFileName(output, _values); @@ -223,7 +222,7 @@ private void DoCreateOnPremTranscription() private void DoApplyOnPremEndpoints() { - var config = _values.GetOrDefault("batch.transcription.onprem.endpoints.config", ""); + var config = _values.GetOrEmpty("batch.transcription.onprem.endpoints.config"); if (string.IsNullOrEmpty(config)) { _values.AddThrowError( @@ -342,9 +341,9 @@ private void DoList(string kind = "") UrlHelpers.CheckWriteOutputUrlsOrIds(json, "values", "self", _values, "batch"); } - private string DoDownload() + private string? DoDownload() { - var url = _values.GetOrDefault("batch.download.url", ""); + var url = _values.GetOrEmpty("batch.download.url"); var urlOk = !string.IsNullOrEmpty(url); if (urlOk) return DownloadUrl(url); @@ -375,7 +374,7 @@ private string DoDownload() private void DoCreateTranscription() { - var name = _values.GetOrDefault("batch.transcription.name", ""); + var name = _values.GetOrEmpty("batch.transcription.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -400,7 +399,7 @@ private void DoCreateTranscription() private void DoUpdateTranscription() { - var id = _values.GetOrDefault("batch.transcription.id", ""); + var id = _values.GetOrEmpty("batch.transcription.id"); var message = $"Updating transcription '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -416,7 +415,7 @@ private void DoUpdateTranscription() private void DoDeleteTranscription() { - var id = _values.GetOrDefault("batch.transcription.id", ""); + var id = _values.GetOrEmpty("batch.transcription.id"); var message = $"Deleting transcription '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -432,7 +431,7 @@ private void DoDeleteTranscription() private void DoTranscriptionStatus() { - var id = _values.GetOrDefault("batch.transcription.id", ""); + var id = _values.GetOrEmpty("batch.transcription.id"); var message = $"Getting status for transcription {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -455,7 +454,7 @@ private void GetListParameters(string kind, out string path, out string message, var listLanguages = _values.GetOrDefault("batch.list.languages", false); var languageKind = _values.GetOrDefault("batch.list.languages.kind", listLanguages ? kind.TrimEnd('s') : ""); - var listId = _values.GetOrDefault("download.list.id", ""); + var listId = _values.GetOrEmpty("download.list.id"); var transcriptionId = IdHelpers.GetIdFromNamedValue(_values, "batch.transcription.id", listId); var transcriptionFiles = _values.GetOrDefault("batch.list.transcription.files", false); if (transcriptionFiles && string.IsNullOrEmpty(transcriptionId)) @@ -489,8 +488,8 @@ private void GetListParameters(string kind, out string path, out string message, "SEE:", $"{Program.Name} help batch transcription"); } - var top = _values.GetOrDefault("batch.top", ""); - var skip = _values.GetOrDefault("batch.skip", ""); + var top = _values.GetOrEmpty("batch.top"); + var skip = _values.GetOrEmpty("batch.skip"); query = ""; if (!string.IsNullOrEmpty(skip)) query += $"&skip={skip}"; @@ -515,7 +514,7 @@ private void GetDownloadParameters(out string path, out string query, out string private void CheckDownloadFile(ref string path, ref string message) { - var file = _values.GetOrDefault("batch.download.file", ""); + var file = _values.GetOrEmpty("batch.download.file"); var fileOk = !string.IsNullOrEmpty(file) && file.StartsWith("http"); if (fileOk) @@ -530,10 +529,10 @@ private void CheckDownloadFile(ref string path, ref string message) private void CheckDownloadTranscriptionFile(ref string path, ref string message) { - var transcriptionFile = _values.GetOrDefault("batch.transcription.file.id", ""); + var transcriptionFile = _values.GetOrEmpty("batch.transcription.file.id"); var transcriptionFileOk = !string.IsNullOrEmpty(transcriptionFile) && transcriptionFile.StartsWith("http"); - var downloadId = _values.GetOrDefault("batch.download.id", ""); + var downloadId = _values.GetOrEmpty("batch.download.id"); var transcriptionId = IdHelpers.GetIdFromNamedValue(_values, "batch.transcription.id", downloadId); var transcriptionFileId = IdHelpers.GetIdFromNamedValue(_values, "batch.transcription.file.id"); @@ -554,22 +553,22 @@ private void CheckDownloadTranscriptionFile(ref string path, ref string message) private string GetCreateTranscriptionPostJson(string name) { - var projectId = _values.GetOrDefault("batch.project.id", ""); + var projectId = _values.GetOrEmpty("batch.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; - var modelId = _values.GetOrDefault("batch.transcription.create.model.id", ""); + var modelId = _values.GetOrEmpty("batch.transcription.create.model.id"); var modelUrl = GetCustomSpeechUrl(region, "models", modelId); var modelRef = !string.IsNullOrEmpty(modelId) ? $"\"model\": {{ \"self\": \"{modelUrl}\" }}, " : ""; - var datasetId = _values.GetOrDefault("batch.transcription.create.dataset.id", ""); + var datasetId = _values.GetOrEmpty("batch.transcription.create.dataset.id"); var datasetUrl = GetCustomSpeechUrl(region, "datasets", datasetId); var datasetRef = !string.IsNullOrEmpty(datasetId) ? $"\"dataset\": {{ \"self\": \"{datasetUrl}\" }}, " : ""; StringBuilder sb = new StringBuilder(); - var urls = _values.GetOrDefault("batch.transcription.create.content.urls", _values.GetOrDefault("batch.transcription.create.content.url", "")); + var urls = _values.GetOrDefault("batch.transcription.create.content.urls", _values.GetOrEmpty("batch.transcription.create.content.url")); var urlList = urls.Split(";\r\n".ToCharArray()).ToList(); Predicate fileLikeUrl = url => !url.StartsWith("@") && !url.StartsWith("http"); @@ -595,28 +594,28 @@ private string GetCreateTranscriptionPostJson(string name) var contentUrlRefs = contentUrls.Length > 0 ? $"\"contentUrls\": [ {contentUrls} ]," : ""; var language = _values.GetOrDefault("batch.transcription.language", "en-US"); - var description = _values.GetOrDefault("batch.transcription.description", ""); + var description = _values.GetOrEmpty("batch.transcription.description"); return $"{{ {projectRef} {modelRef} {datasetRef} {contentUrlRefs} \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } private string GetUpdateTranscriptionPostJson() { - var name = _values.GetOrDefault("batch.transcription.name", ""); - var description = _values.GetOrDefault("batch.transcription.description", ""); + var name = _values.GetOrEmpty("batch.transcription.name"); + var description = _values.GetOrEmpty("batch.transcription.description"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("batch.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("batch.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; return $"{{ {projectRef} \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } - private HttpWebRequest CreateWebRequest(string method, string path, string id = null, string query = null, string contentType = null) + private HttpWebRequest CreateWebRequest(string method, string path, string? id = null, string? query = null, string? contentType = null) { - var key = _values.GetOrDefault("service.config.key", ""); - var region = _values.GetOrDefault("service.config.region", ""); + var key = _values.GetOrEmpty("service.config.key"); + var region = _values.GetOrEmpty("service.config.region"); var timeout = _values.GetOrDefault("batch.wait.timeout", 100000); if (string.IsNullOrEmpty(region) || string.IsNullOrEmpty(key)) @@ -654,7 +653,7 @@ private string GetOnPremBatchUrl() return url; } - private string GetCustomSpeechUrl(string region, string path, string id = null, string query = null) + private string GetCustomSpeechUrl(string region, string path, string? id = null, string? query = null) { if (path.StartsWith("http")) return path; @@ -673,7 +672,7 @@ private string GetCustomSpeechUrl(string region, string path, string id = null, private string CheckWriteOutputRequest(HttpWebRequest request, string payload = null, bool append = false) { - var output = _values.GetOrDefault("batch.output.request.file", ""); + var output = _values.GetOrEmpty("batch.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); @@ -689,7 +688,7 @@ private bool CheckWaitForComplete(HttpWebResponse created, string statusJson, st return HttpHelpers.CheckWaitForComplete(created, statusJson, createWebRequest, _values, domain, message, _quiet, _verbose); } - private string DownloadUrl(string url, string defaultFileName = null) + private string? DownloadUrl(string url, string defaultFileName = null) { var message = url.Substring(0, Math.Min(100, url.Length)); message = url.Length > 100 @@ -706,7 +705,7 @@ private string DownloadUrl(string url, string defaultFileName = null) return ReadWritePrintResponse(response, defaultFileName); } - private string ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) + private string? ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) { var saveAs = HttpHelpers.GetOutputDataFileName(defaultFileName, response, _values, "batch", out _, out bool isJson); diff --git a/src/extensions/speech_extension/commands/conversation_transcription_command.cs b/src/extensions/speech_extension/commands/conversation_transcription_command.cs index 4fc311bf..0219f0f1 100644 --- a/src/extensions/speech_extension/commands/conversation_transcription_command.cs +++ b/src/extensions/speech_extension/commands/conversation_transcription_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class ConversationTranscriptionCommand : Command { - internal ConversationTranscriptionCommand(ICommandValues values) + internal ConversationTranscriptionCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } internal bool RunCommand() @@ -31,7 +30,7 @@ internal bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { switch (recognize) { @@ -72,15 +71,15 @@ private void RecognizeContinuous() private ConversationTranscriber CreateConversationTranscriber() { - SpeechConfig config = CreateSpeechConfig(); + var config = CreateSpeechConfig(); - AudioConfig audioConfig = ConfigHelpers.CreateAudioConfig(_values); + var audioConfig = ConfigHelpers.CreateAudioConfig(_values); var transcriber = new ConversationTranscriber(config, audioConfig); _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(transcriber); - _output.EnsureCachePropertyCollection("recognizer", transcriber.Properties); + _output!.EnsureCachePropertyCollection("recognizer", transcriber.Properties); return transcriber; } @@ -102,7 +101,7 @@ private SpeechConfig CreateSpeechConfig() _values.AddThrowError("ERROR:", $"Creating SpeechConfig; use of region requires one of: key or token."); } - SpeechConfig config = null; + SpeechConfig? config = null; if (!string.IsNullOrEmpty(endpoint)) { config = string.IsNullOrEmpty(key) @@ -144,7 +143,7 @@ private void SetSpeechConfigProperties(SpeechConfig config) var endpointId = _values["service.config.endpoint.id"]; if (!string.IsNullOrEmpty(endpointId)) config.EndpointId = endpointId; - var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; var profanity = _values["service.output.config.profanity.option"]; @@ -161,10 +160,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); var rtf = _values.GetOrDefault("audio.input.real.time.factor", -1); @@ -173,10 +172,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var fastLane = _values.GetOrDefault("audio.input.fast.lane", rtf >= 0 ? 0 : -1); if (fastLane >= 0) config.SetProperty("SPEECH-TransmitLengthBeforThrottleMs", fastLane.ToString()); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); // config.SetProperty("AudioConfig_NumberOfChannelsForCapture", "8"); @@ -245,7 +244,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -266,7 +265,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -291,9 +290,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -307,14 +305,14 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } private KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -374,70 +372,70 @@ private void RecognizerConnectionConnect(Connection connection, bool continuous) private void RecognizerConnectionDisconnect(ConversationTranscriber transcriber) { - _lock.EnterReaderLockOnce(ref _expectDisconnected); + _lock!.EnterReaderLockOnce(ref _expectDisconnected); var connection = Connection.FromRecognizer(transcriber); connection.Close(); } - private void Connected(object sender, ConnectionEventArgs e) + private void Connected(object? sender, ConnectionEventArgs e) { - _display.DisplayConnected(e); - _output.Connected(e); + _display!.DisplayConnected(e); + _output!.Connected(e); } - private void Disconnected(object sender, ConnectionEventArgs e) + private void Disconnected(object? sender, ConnectionEventArgs e) { - _display.DisplayDisconnected(e); - _output.Disconnected(e); + _display!.DisplayDisconnected(e); + _output!.Disconnected(e); - _lock.ExitReaderLockOnce(ref _expectDisconnected); + _lock!.ExitReaderLockOnce(ref _expectDisconnected); } - private void ConnectionMessageReceived(object sender, ConnectionMessageEventArgs e) + private void ConnectionMessageReceived(object? sender, ConnectionMessageEventArgs e) { - _display.DisplayMessageReceived(e); - _output.ConnectionMessageReceived(e); + _display!.DisplayMessageReceived(e); + _output!.ConnectionMessageReceived(e); } - private void SessionStarted(object sender, SessionEventArgs e) + private void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - private void SessionStopped(object sender, SessionEventArgs e) + private void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - private void Transcribing(object sender, ConversationTranscriptionEventArgs e) + private void Transcribing(object? sender, ConversationTranscriptionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayTranscribing(e); - _output.Transcribing(e); + _display!.DisplayTranscribing(e); + _output!.Transcribing(e); } - private void Transcribed(object sender, ConversationTranscriptionEventArgs e) + private void Transcribed(object? sender, ConversationTranscriptionEventArgs e) { - _display.DisplayTranscribed(e); - _output.Transcribed(e); + _display!.DisplayTranscribed(e); + _output!.Transcribed(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - private void Canceled(object sender, ConversationTranscriptionCanceledEventArgs e) + private void Canceled(object? sender, ConversationTranscriptionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } @@ -466,15 +464,15 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -486,22 +484,22 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } private bool _microphone = false; private bool _connect = false; private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectRecognized = 0; private int _expectSessionStopped = 0; private int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/custom_speech_recognition_command.cs b/src/extensions/speech_extension/commands/custom_speech_recognition_command.cs index 25944206..8a77c260 100644 --- a/src/extensions/speech_extension/commands/custom_speech_recognition_command.cs +++ b/src/extensions/speech_extension/commands/custom_speech_recognition_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class CustomSpeechRecognitionCommand : Command { - public CustomSpeechRecognitionCommand(ICommandValues values) + public CustomSpeechRecognitionCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -146,9 +145,9 @@ private void DoList(string kind = "") UrlHelpers.CheckWriteOutputUrlsOrIds(json, "values", "self", _values, "csr"); } - private string DoDownload() + private string? DoDownload() { - var url = _values.GetOrDefault("csr.download.url", ""); + var url = _values.GetOrEmpty("csr.download.url"); var urlOk = !string.IsNullOrEmpty(url); if (urlOk) return DownloadUrl(url); @@ -179,7 +178,7 @@ private string DoDownload() private void DoCreateProject() { - var name = _values.GetOrDefault("csr.project.name", ""); + var name = _values.GetOrEmpty("csr.project.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -202,7 +201,7 @@ private void DoCreateProject() private void DoUpdateProject() { - var id = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.project.id"); var message = $"Updating project '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -218,7 +217,7 @@ private void DoUpdateProject() private void DoDeleteProject() { - var id = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.project.id"); var message = $"Deleting project '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -234,7 +233,7 @@ private void DoDeleteProject() private void DoProjectStatus() { - var id = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.project.id"); var message = $"Getting status for project {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -251,7 +250,7 @@ private void DoProjectStatus() private void DoCreateDataset() { - var name = _values.GetOrDefault("csr.dataset.name", ""); + var name = _values.GetOrEmpty("csr.dataset.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -276,7 +275,7 @@ private void DoCreateDataset() private void DoUploadDataset() { - var name = _values.GetOrDefault("csr.dataset.name", ""); + var name = _values.GetOrEmpty("csr.dataset.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -306,7 +305,7 @@ private void DoUploadDataset() private void DoUpdateDataset() { - var id = _values.GetOrDefault("csr.dataset.id", ""); + var id = _values.GetOrEmpty("csr.dataset.id"); var message = $"Updating dataset '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -322,7 +321,7 @@ private void DoUpdateDataset() private void DoDeleteDataset() { - var id = _values.GetOrDefault("csr.dataset.id", ""); + var id = _values.GetOrEmpty("csr.dataset.id"); var message = $"Deleting dataset {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -338,8 +337,8 @@ private void DoDeleteDataset() private void DoDatasetStatus() { - var id = _values.GetOrDefault("csr.dataset.id", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.dataset.id"); + var projectId = _values.GetOrEmpty("csr.project.id"); if (!string.IsNullOrEmpty(projectId)) { @@ -364,7 +363,7 @@ private void DoDatasetStatus() private void DoCreateModel() { - var name = _values.GetOrDefault("csr.model.name", ""); + var name = _values.GetOrEmpty("csr.model.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -389,7 +388,7 @@ private void DoCreateModel() private void DoUpdateModel() { - var id = _values.GetOrDefault("csr.model.id", ""); + var id = _values.GetOrEmpty("csr.model.id"); var message = $"Updating model '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -405,7 +404,7 @@ private void DoUpdateModel() private void DoDeleteModel() { - var id = _values.GetOrDefault("csr.model.id", ""); + var id = _values.GetOrEmpty("csr.model.id"); var message = $"Deleting model {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -421,8 +420,8 @@ private void DoDeleteModel() private void DoModelStatus() { - var id = _values.GetOrDefault("csr.model.id", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.model.id"); + var projectId = _values.GetOrEmpty("csr.project.id"); if (!string.IsNullOrEmpty(projectId)) { @@ -447,9 +446,9 @@ private void DoModelStatus() private void DoModelCopy() { - var id = _values.GetOrDefault("csr.model.id", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); - var targetKey = _values.GetOrDefault("csr.model.copy.target.key", ""); + var id = _values.GetOrEmpty("csr.model.id"); + var projectId = _values.GetOrEmpty("csr.project.id"); + var targetKey = _values.GetOrEmpty("csr.model.copy.target.key"); if (!string.IsNullOrEmpty(projectId)) { @@ -479,7 +478,7 @@ private void DoModelCopy() private void DoCreateEvaluation() { - var name = _values.GetOrDefault("csr.evaluation.name", ""); + var name = _values.GetOrEmpty("csr.evaluation.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -504,7 +503,7 @@ private void DoCreateEvaluation() private void DoUpdateEvaluation() { - var id = _values.GetOrDefault("csr.evaluation.id", ""); + var id = _values.GetOrEmpty("csr.evaluation.id"); var message = $"Updating evaluation '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -520,7 +519,7 @@ private void DoUpdateEvaluation() private void DoDeleteEvaluation() { - var id = _values.GetOrDefault("csr.evaluation.id", ""); + var id = _values.GetOrEmpty("csr.evaluation.id"); var message = $"Deleting evaluation {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -536,8 +535,8 @@ private void DoDeleteEvaluation() private void DoEvaluationStatus() { - var id = _values.GetOrDefault("csr.evaluation.id", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.evaluation.id"); + var projectId = _values.GetOrEmpty("csr.project.id"); if (!string.IsNullOrEmpty(projectId)) { @@ -562,7 +561,7 @@ private void DoEvaluationStatus() private void DoCreateEndpoint() { - var name = _values.GetOrDefault("csr.endpoint.name", ""); + var name = _values.GetOrEmpty("csr.endpoint.name"); if (string.IsNullOrEmpty(name)) { _values.AddThrowError( @@ -587,7 +586,7 @@ private void DoCreateEndpoint() private void DoUpdateEndpoint() { - var id = _values.GetOrDefault("csr.endpoint.id", ""); + var id = _values.GetOrEmpty("csr.endpoint.id"); var message = $"Updating endpoint '{id}' ..."; if (!_quiet) Console.WriteLine(message); @@ -603,7 +602,7 @@ private void DoUpdateEndpoint() private void DoDeleteEndpoint() { - var id = _values.GetOrDefault("csr.endpoint.id", ""); + var id = _values.GetOrEmpty("csr.endpoint.id"); var message = $"Deleting endpoint {id} ..."; if (!_quiet) Console.WriteLine(message); @@ -619,8 +618,8 @@ private void DoDeleteEndpoint() private void DoEndpointStatus() { - var id = _values.GetOrDefault("csr.endpoint.id", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var id = _values.GetOrEmpty("csr.endpoint.id"); + var projectId = _values.GetOrEmpty("csr.project.id"); if (!string.IsNullOrEmpty(projectId)) { @@ -650,12 +649,12 @@ private void GetListParameters(string kind, out string path, out string message, var listLanguages = _values.GetOrDefault("csr.list.languages", false); var languageKind = _values.GetOrDefault("csr.list.languages.kind", listLanguages ? kind.TrimEnd('s') : ""); - var list = _values.GetOrDefault("csr.list.id", ""); + var list = _values.GetOrEmpty("csr.list.id"); var listOk = list.StartsWith("http"); var listId = listOk ? "" : list; - var dataset = _values.GetOrDefault("csr.dataset.id", ""); + var dataset = _values.GetOrEmpty("csr.dataset.id"); var datasetOk = !string.IsNullOrEmpty(dataset) && dataset.StartsWith("http"); var kindIsDatasets = kind == "datasets"; @@ -670,7 +669,7 @@ private void GetListParameters(string kind, out string path, out string message, "USE:", $"{Program.Name} csr dataset list --dataset ID/URL --files"); } - var evaluation = _values.GetOrDefault("csr.evaluation.id", ""); + var evaluation = _values.GetOrEmpty("csr.evaluation.id"); var evaluationOk = !string.IsNullOrEmpty(evaluation) && evaluation.StartsWith("http"); var kindIsEvaluations = kind == "evaluations"; @@ -685,7 +684,7 @@ private void GetListParameters(string kind, out string path, out string message, "USE:", $"{Program.Name} csr evaluation list --evaluation ID/URL --files"); } - var endpoint = _values.GetOrDefault("csr.endpoint.id", ""); + var endpoint = _values.GetOrEmpty("csr.endpoint.id"); var endpointOk = !string.IsNullOrEmpty(endpoint) && endpoint.StartsWith("http"); var kindIsEndpoints = kind == "endpoints"; @@ -767,8 +766,8 @@ private void GetListParameters(string kind, out string path, out string message, "SEE:", $"{Program.Name} help csr"); } - var top = _values.GetOrDefault("csr.top", ""); - var skip = _values.GetOrDefault("csr.skip", ""); + var top = _values.GetOrEmpty("csr.top"); + var skip = _values.GetOrEmpty("csr.skip"); query = ""; if (!string.IsNullOrEmpty(skip)) query += $"&skip={skip}"; @@ -795,7 +794,7 @@ private void GetDownloadParameters(out string path, out string query, out string private void CheckDownloadFile(ref string path, ref string message) { - var file = _values.GetOrDefault("csr.download.file", ""); + var file = _values.GetOrEmpty("csr.download.file"); var fileOk = !string.IsNullOrEmpty(file) && file.StartsWith("http"); if (fileOk) @@ -810,10 +809,10 @@ private void CheckDownloadFile(ref string path, ref string message) private void CheckDownloadDatasetFile(ref string path, ref string message) { - var datasetFile = _values.GetOrDefault("csr.dataset.file.id", ""); + var datasetFile = _values.GetOrEmpty("csr.dataset.file.id"); var datasetFileOk = !string.IsNullOrEmpty(datasetFile) && datasetFile.StartsWith("http"); - var downloadId = _values.GetOrDefault("csr.download.id", ""); + var downloadId = _values.GetOrEmpty("csr.download.id"); var datasetId = IdHelpers.GetIdFromNamedValue(_values, "csr.dataset.id", downloadId); var datasetIdOk = !string.IsNullOrEmpty(datasetId); @@ -834,10 +833,10 @@ private void CheckDownloadDatasetFile(ref string path, ref string message) private void CheckDownloadEvaluationFile(ref string path, ref string message) { - var evaluationFile = _values.GetOrDefault("csr.evaluation.file.id", ""); + var evaluationFile = _values.GetOrEmpty("csr.evaluation.file.id"); var evaluationFileOk = !string.IsNullOrEmpty(evaluationFile) && evaluationFile.StartsWith("http"); - var downloadId = _values.GetOrDefault("csr.download.id", ""); + var downloadId = _values.GetOrEmpty("csr.download.id"); var evaluationId = IdHelpers.GetIdFromNamedValue(_values, "csr.evaluation.id", downloadId); var evaluationIdOk = !string.IsNullOrEmpty(evaluationId); @@ -858,10 +857,10 @@ private void CheckDownloadEvaluationFile(ref string path, ref string message) private void CheckDownloadEndpointLog(ref string path, ref string message) { - var endpointLog = _values.GetOrDefault("csr.endpoint.log.id", ""); + var endpointLog = _values.GetOrEmpty("csr.endpoint.log.id"); var endpointLogOk = !string.IsNullOrEmpty(endpointLog) && endpointLog.StartsWith("http"); - var downloadId = _values.GetOrDefault("csr.download.id", ""); + var downloadId = _values.GetOrEmpty("csr.download.id"); var endpointId = IdHelpers.GetIdFromNamedValue(_values, "csr.endpoint.id", downloadId); var endpointIdOk = !string.IsNullOrEmpty(endpointId); @@ -883,17 +882,17 @@ private void CheckDownloadEndpointLog(ref string path, ref string message) private string GetCreateProjectPostJson(string name) { var language = _values.GetOrDefault("csr.project.language", "en-US"); - var description = _values.GetOrDefault("csr.project.description", ""); + var description = _values.GetOrEmpty("csr.project.description"); return $"{{ \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } private string GetUpdateProjectPostJson() { - var name = _values.GetOrDefault("csr.project.name", ""); - var description = _values.GetOrDefault("csr.project.description", ""); + var name = _values.GetOrEmpty("csr.project.name"); + var description = _values.GetOrEmpty("csr.project.description"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("csr.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; @@ -902,18 +901,18 @@ private string GetUpdateProjectPostJson() private string GetCreateModelPostJson(string name) { - var projectId = _values.GetOrDefault("csr.project.id", ""); + var projectId = _values.GetOrEmpty("csr.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; - var baseId = _values.GetOrDefault("csr.model.create.base.model.id", ""); + var baseId = _values.GetOrEmpty("csr.model.create.base.model.id"); var baseUrl = GetCustomSpeechUrl(region, "models/base", baseId); var baseRef = !string.IsNullOrEmpty(baseId) ? $"\"baseModel\": {{ \"self\": \"{baseUrl}\" }}," : ""; StringBuilder sb = new StringBuilder(); - var datasetIds = _values.GetOrDefault("csr.model.create.dataset.ids", _values.GetOrDefault("csr.model.create.dataset.id", "")); + var datasetIds = _values.GetOrDefault("csr.model.create.dataset.ids", _values.GetOrEmpty("csr.model.create.dataset.id")); foreach (var datasetId in datasetIds.Split(";\r\n".ToCharArray())) { if (!string.IsNullOrEmpty(datasetId)) @@ -926,22 +925,22 @@ private string GetCreateModelPostJson(string name) var datasets = sb.ToString().Trim(',', ' '); var datasetRefs = datasets.Length > 0 ? $"\"datasets\": [ {datasets} ]," : ""; - var text = _values.GetOrDefault("csr.model.create.text", ""); + var text = _values.GetOrEmpty("csr.model.create.text"); var textRef = !string.IsNullOrEmpty(text) ? $"\"text\": \"{text}\"," : ""; var language = _values.GetOrDefault("csr.model.language", "en-US"); - var description = _values.GetOrDefault("csr.model.description", ""); + var description = _values.GetOrEmpty("csr.model.description"); return $"{{ {projectRef} {baseRef} {datasetRefs} {textRef} \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } private string GetUpdateModelPostJson() { - var name = _values.GetOrDefault("csr.model.name", ""); - var description = _values.GetOrDefault("csr.model.description", ""); + var name = _values.GetOrEmpty("csr.model.name"); + var description = _values.GetOrEmpty("csr.model.description"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("csr.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; @@ -955,37 +954,37 @@ private string GetCopyModelPostJson(string targetKey) private string GetCreateEvaluationPostJson(string name) { - var projectId = _values.GetOrDefault("csr.project.id", ""); + var projectId = _values.GetOrEmpty("csr.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; - var modelId1 = _values.GetOrDefault("csr.evaluation.create.model1.id", ""); + var modelId1 = _values.GetOrEmpty("csr.evaluation.create.model1.id"); var modelUrl1 = GetCustomSpeechUrl(region, "models", modelId1); var modelRef1 = !string.IsNullOrEmpty(modelId1) ? $"\"model1\": {{ \"self\": \"{modelUrl1}\" }}," : ""; - var modelId2 = _values.GetOrDefault("csr.evaluation.create.model2.id", ""); + var modelId2 = _values.GetOrEmpty("csr.evaluation.create.model2.id"); var modelUrl2 = GetCustomSpeechUrl(region, "models", modelId2); var modelRef2 = !string.IsNullOrEmpty(modelId2) ? $"\"model2\": {{ \"self\": \"{modelUrl2}\" }}," : ""; - var datasetId = _values.GetOrDefault("csr.evaluation.create.dataset.id", ""); + var datasetId = _values.GetOrEmpty("csr.evaluation.create.dataset.id"); var datasetUrl = GetCustomSpeechUrl(region, "datasets", datasetId); var datasetRef = !string.IsNullOrEmpty(modelId1) ? $"\"dataset\": {{ \"self\": \"{datasetUrl}\" }}," : ""; var language = _values.GetOrDefault("csr.evaluation.language", "en-US"); - var description = _values.GetOrDefault("csr.evaluation.description", ""); + var description = _values.GetOrEmpty("csr.evaluation.description"); return $"{{ {projectRef} {modelRef1} {modelRef2} {datasetRef} \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } private string GetUpdateEvaluationPostJson() { - var name = _values.GetOrDefault("csr.evaluation.name", ""); - var description = _values.GetOrDefault("csr.evaluation.description", ""); + var name = _values.GetOrEmpty("csr.evaluation.name"); + var description = _values.GetOrEmpty("csr.evaluation.description"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("csr.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; @@ -994,23 +993,23 @@ private string GetUpdateEvaluationPostJson() private string GetCreateDatasetPostJson(string name) { - var contentUrl = _values.GetOrDefault("csr.dataset.create.content.url", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var contentUrl = _values.GetOrEmpty("csr.dataset.create.content.url"); + var projectId = _values.GetOrEmpty("csr.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; - var kind = _values.GetOrDefault("csr.dataset.kind", ""); + var kind = _values.GetOrEmpty("csr.dataset.kind"); var language = _values.GetOrDefault("csr.dataset.language", "en-US"); - var description = _values.GetOrDefault("csr.dataset.description", ""); + var description = _values.GetOrEmpty("csr.dataset.description"); return $"{{ {projectRef} \"kind\": \"{kind}\", \"contentUrl\": \"{contentUrl}\", \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; } private byte[] GetUploadDatasetPostFormData(string name, string boundary) { - var dataFile = _values.GetOrDefault("csr.dataset.upload.data.file", ""); + var dataFile = _values.GetOrEmpty("csr.dataset.upload.data.file"); if (string.IsNullOrEmpty(dataFile)) { _values.AddThrowError( @@ -1024,14 +1023,14 @@ private byte[] GetUploadDatasetPostFormData(string name, string boundary) _values.AddThrowError("ERROR:", $"Cannot find data file: \"{dataFile}\""); } - var projectId = _values.GetOrDefault("csr.project.id", ""); + var projectId = _values.GetOrEmpty("csr.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); - var kind = _values.GetOrDefault("csr.dataset.kind", ""); + var kind = _values.GetOrEmpty("csr.dataset.kind"); var language = _values.GetOrDefault("csr.dataset.language", "en-US"); - var description = _values.GetOrDefault("csr.dataset.description", ""); + var description = _values.GetOrEmpty("csr.dataset.description"); var sb = new StringBuilder(); @@ -1050,7 +1049,7 @@ private byte[] GetUploadDatasetPostFormData(string name, string boundary) sb.Append($"--{boundary}\r\nContent-Disposition: form-data; name=\"data\"; filename=\"{dataFile}\"\r\nContent-Type: {contentType}\r\n\r\n"); var bytes1 = Encoding.UTF8.GetBytes(sb.ToString()); - var bytes2 = FileHelpers.ReadAllBytes(zipFile); + var bytes2 = FileHelpers.ReadAllBytes(zipFile!); var bytes3 = Encoding.UTF8.GetBytes($"\r\n--{boundary}--\r\n"); var bytes = new byte[bytes1.Length + bytes2.Length + bytes3.Length]; @@ -1063,11 +1062,11 @@ private byte[] GetUploadDatasetPostFormData(string name, string boundary) private string GetUpdateDatasetPostJson() { - var name = _values.GetOrDefault("csr.dataset.name", ""); - var description = _values.GetOrDefault("csr.dataset.description", ""); + var name = _values.GetOrEmpty("csr.dataset.name"); + var description = _values.GetOrEmpty("csr.dataset.description"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("csr.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; @@ -1076,21 +1075,21 @@ private string GetUpdateDatasetPostJson() private string GetCreateEndpointPostJson(string name) { - var projectId = _values.GetOrDefault("csr.project.id", ""); + var projectId = _values.GetOrEmpty("csr.project.id"); - var region = _values.GetOrDefault("service.config.region", ""); + var region = _values.GetOrEmpty("service.config.region"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; - var modelId = _values.GetOrDefault("csr.endpoint.create.model.id", ""); + var modelId = _values.GetOrEmpty("csr.endpoint.create.model.id"); var modelUrl = GetCustomSpeechUrl(region, "models", modelId); var modelRef = !string.IsNullOrEmpty(modelId) ? $"\"model\": {{ \"self\": \"{modelUrl}\" }}, " : ""; - var text = _values.GetOrDefault("csr.endpoint.create.text", ""); + var text = _values.GetOrEmpty("csr.endpoint.create.text"); var textRef = !string.IsNullOrEmpty(text) ? $"\"text\": \"{text}\"," : ""; var language = _values.GetOrDefault("csr.endpoint.language", "en-US"); - var description = _values.GetOrDefault("csr.endpoint.description", ""); + var description = _values.GetOrEmpty("csr.endpoint.description"); var properties = GetProperties("endpoint"); return $"{{ {projectRef} {modelRef} {textRef} {properties} \"locale\": \"{language}\", \"displayName\": \"{name}\", \"description\": \"{description}\" }}"; @@ -1098,12 +1097,12 @@ private string GetCreateEndpointPostJson(string name) private string GetUpdateEndpointPostJson() { - var name = _values.GetOrDefault("csr.endpoint.name", ""); - var description = _values.GetOrDefault("csr.endpoint.description", ""); + var name = _values.GetOrEmpty("csr.endpoint.name"); + var description = _values.GetOrEmpty("csr.endpoint.description"); var properties = GetProperties("endpoint"); - var region = _values.GetOrDefault("service.config.region", ""); - var projectId = _values.GetOrDefault("csr.project.id", ""); + var region = _values.GetOrEmpty("service.config.region"); + var projectId = _values.GetOrEmpty("csr.project.id"); var projectUrl = GetCustomSpeechUrl(region, "projects", projectId); var projectRef = !string.IsNullOrEmpty(projectId) ? $"\"project\": {{ \"self\": \"{projectUrl}\" }}," : ""; @@ -1118,10 +1117,10 @@ private string GetProperties(string thing) return $"\"properties\": {{ {loggingPart} }},"; } - private HttpWebRequest CreateWebRequest(string method, string path, string id = null, string query = null, string contentType = null) + private HttpWebRequest CreateWebRequest(string method, string path, string? id = null, string? query = null, string? contentType = null) { - var key = _values.GetOrDefault("service.config.key", ""); - var region = _values.GetOrDefault("service.config.region", ""); + var key = _values.GetOrEmpty("service.config.key"); + var region = _values.GetOrEmpty("service.config.region"); var timeout = _values.GetOrDefault("csr.wait.timeout", 100000); if (string.IsNullOrEmpty(region) || string.IsNullOrEmpty(key)) @@ -1149,7 +1148,7 @@ private HttpWebRequest CreateWebRequest(string method, string path, string id = return request; } - private string GetCustomSpeechUrl(string region, string path, string id = null, string query = null) + private string GetCustomSpeechUrl(string region, string path, string? id = null, string? query = null) { if (path.StartsWith("http")) return path; @@ -1168,7 +1167,7 @@ private string GetCustomSpeechUrl(string region, string path, string id = null, private string CheckWriteOutputRequest(HttpWebRequest request, string payload = null, bool append = false) { - var output = _values.GetOrDefault("csr.output.request.file", ""); + var output = _values.GetOrEmpty("csr.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); @@ -1184,7 +1183,7 @@ private bool CheckWaitForComplete(HttpWebResponse created, string statusJson, st return HttpHelpers.CheckWaitForComplete(created, statusJson, createWebRequest, _values, domain, message, _quiet, _verbose); } - private string DownloadUrl(string url, string defaultFileName = null) + private string? DownloadUrl(string url, string defaultFileName = null) { var message = url.Substring(0, Math.Min(100, url.Length)); message = url.Length > 100 @@ -1201,7 +1200,7 @@ private string DownloadUrl(string url, string defaultFileName = null) return ReadWritePrintResponse(response, defaultFileName); } - private string ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) + private string? ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) { var saveAs = HttpHelpers.GetOutputDataFileName(defaultFileName, response, _values, "csr", out _, out bool isJson); diff --git a/src/extensions/speech_extension/commands/dialog_command.cs b/src/extensions/speech_extension/commands/dialog_command.cs index ca3bc99a..ec824b94 100644 --- a/src/extensions/speech_extension/commands/dialog_command.cs +++ b/src/extensions/speech_extension/commands/dialog_command.cs @@ -24,10 +24,8 @@ public enum DialogType public class DialogCommand : RecognizeCommandBase { - internal DialogCommand(ICommandValues values) + internal DialogCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); - _activityReceivedTimeout = _values.GetOrDefault("recognize.timeout", _microphone ? 10000 : int.MaxValue); } @@ -37,7 +35,7 @@ internal bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { StartCommand(); @@ -124,12 +122,12 @@ private DialogServiceConnector CreateDialogServiceConnector() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(connector); - // _output.EnsureCachePropertyCollection("recognizer", connector.Properties); + // _output!.EnsureCachePropertyCollection("recognizer", connector.Properties); return connector; } - private DialogServiceConfig CreateDialogServiceConfig(string key = null, string region = null, string botId = null, string ccAppId = null) + private DialogServiceConfig CreateDialogServiceConfig(string? key = null, string? region = null, string? botId = null, string? ccAppId = null) { key = string.IsNullOrEmpty(key) ? _values["service.config.key"] : key; region = string.IsNullOrEmpty(region) ? _values["service.config.region"] : region; @@ -171,18 +169,18 @@ private DialogServiceConfig CreateDialogServiceConfig(string key = null, string return config; } - private new void Recognized(object sender, SpeechRecognitionEventArgs e) + private new void Recognized(object? sender, SpeechRecognitionEventArgs e) { base.Recognized(sender, e); if (e.Result.Reason == ResultReason.RecognizedKeyword) { - _connector.StopKeywordRecognitionAsync().Wait(); + _connector!.StopKeywordRecognitionAsync().Wait(); _keywordRecognizedEvent.Set(); } } - private void ActivityReceived(object sender, ActivityReceivedEventArgs e) + private void ActivityReceived(object? sender, ActivityReceivedEventArgs e) { var activity = JsonSerializer.Deserialize(e.Activity); if (e.HasAudio && activity?.Speak != null) @@ -241,7 +239,7 @@ private void PrintToConsole(string text) Console.WriteLine($"DIALOG: {text}"); } - private DialogServiceConnector _connector; + private DialogServiceConnector? _connector; private Regex _ssmlRegex = new Regex("()"); private ManualResetEvent _keywordRecognizedEvent = new ManualResetEvent(false); diff --git a/src/extensions/speech_extension/commands/intent_command.cs b/src/extensions/speech_extension/commands/intent_command.cs index 21412864..ccc5fd20 100644 --- a/src/extensions/speech_extension/commands/intent_command.cs +++ b/src/extensions/speech_extension/commands/intent_command.cs @@ -23,9 +23,8 @@ namespace Azure.AI.Details.Common.CLI public class IntentCommand : Command { - public IntentCommand(ICommandValues values) + public IntentCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } public bool RunCommand() @@ -34,7 +33,7 @@ public bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { switch (recognize) { @@ -167,7 +166,7 @@ private IntentRecognizer CreateIntentRecognizer() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(recognizer); - _output.EnsureCachePropertyCollection("recognizer", recognizer.Properties); + _output!.EnsureCachePropertyCollection("recognizer", recognizer.Properties); return recognizer; } @@ -225,10 +224,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var endpointId = _values["service.config.endpoint.id"]; if (!string.IsNullOrEmpty(endpointId)) config.EndpointId = endpointId; - var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; - var profanity = _values.GetOrDefault("service.output.config.profanity.option", "").ToLower(); + var profanity = _values.GetOrEmpty("service.output.config.profanity.option").ToLower(); if (profanity == "removed") config.SetProfanity(ProfanityOption.Removed); if (profanity == "masked") config.SetProfanity(ProfanityOption.Masked); if (profanity == "raw") config.SetProfanity(ProfanityOption.Raw); @@ -242,10 +241,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); var rtf = _values.GetOrDefault("audio.input.real.time.factor", -1); @@ -254,10 +253,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var fastLane = _values.GetOrDefault("audio.input.fast.lane", rtf >= 0 ? 0 : -1); if (fastLane >= 0) config.SetProperty("SPEECH-TransmitLengthBeforThrottleMs", fastLane.ToString()); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); var embedded = _values.GetOrDefault("embedded.config.embedded", false); @@ -271,10 +270,10 @@ private void SetEmbeddedProperties(SpeechConfig config) // Turn on embedded (offline) speech recognition. config.SetProperty("SPEECH-RecoBackend", "offline"); - var modelKey = _values.GetOrDefault("embedded.config.model.key", ""); + var modelKey = _values.GetOrEmpty("embedded.config.model.key"); config.SetProperty("SPEECH-RecoModelKey", modelKey); - var modelPath = _values.GetOrDefault("embedded.config.model.path", ""); + var modelPath = _values.GetOrEmpty("embedded.config.model.path"); var modelIniFileFullPath = Path.GetFullPath(Path.Combine(modelPath, "sr.ini")); if (!File.Exists(modelIniFileFullPath)) { @@ -308,7 +307,7 @@ private void CheckNotYetImplementedConfigProperties() private void CheckAudioInput() { - var id = _values["audio.input.id"]; + var id = _values["audio.input.id"]!; var input = _values["audio.input.type"]; var file = _values["audio.input.file"]; var url = ""; @@ -341,7 +340,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -362,7 +361,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -387,9 +386,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -403,14 +401,14 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } private KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -419,20 +417,20 @@ private KeywordRecognitionModel LoadKeywordModel() private void PrepRecognizerIntents(IntentRecognizer recognizer) { - var appId = _values.GetOrDefault("luis.appid", ""); + var appId = _values.GetOrEmpty("luis.appid"); var model = !string.IsNullOrEmpty(appId) ? LanguageUnderstandingModel.FromAppId(appId) : null; if (model != null) PrepRecognizerLuisIntents(recognizer, model); - var intent = _values.GetOrDefault("intent.pattern", ""); + var intent = _values.GetOrEmpty("intent.pattern"); if (!string.IsNullOrEmpty(intent)) AddIntentPattern(recognizer, intent); - var intents = _values.GetOrDefault("intent.patterns", ""); + var intents = _values.GetOrEmpty("intent.patterns"); if (!string.IsNullOrEmpty(intents)) AddIntentPatterns(recognizer, intents); } private void PrepRecognizerLuisIntents(IntentRecognizer recognizer, LanguageUnderstandingModel model) { - var intent = _values.GetOrDefault("luis.intent", ""); + var intent = _values.GetOrEmpty("luis.intent"); if (!string.IsNullOrEmpty(intent)) PrepRecognizerLuisIntent(recognizer, model, intent); var useAllIntents = _values.GetOrDefault("luis.allintents", string.IsNullOrEmpty(intent)); @@ -542,70 +540,70 @@ private void RecognizerConnectionConnect(Connection connection, bool continuous) private void RecognizerConnectionDisconnect(IntentRecognizer recognizer) { - _lock.EnterReaderLockOnce(ref _expectDisconnected); + _lock!.EnterReaderLockOnce(ref _expectDisconnected); var connection = Connection.FromRecognizer(recognizer); connection.Close(); } - private void Connected(object sender, ConnectionEventArgs e) + private void Connected(object? sender, ConnectionEventArgs e) { - _display.DisplayConnected(e); - _output.Connected(e); + _display!.DisplayConnected(e); + _output!.Connected(e); } - private void Disconnected(object sender, ConnectionEventArgs e) + private void Disconnected(object? sender, ConnectionEventArgs e) { - _display.DisplayDisconnected(e); - _output.Disconnected(e); + _display!.DisplayDisconnected(e); + _output!.Disconnected(e); - _lock.ExitReaderLockOnce(ref _expectDisconnected); + _lock!.ExitReaderLockOnce(ref _expectDisconnected); } - private void ConnectionMessageReceived(object sender, ConnectionMessageEventArgs e) + private void ConnectionMessageReceived(object? sender, ConnectionMessageEventArgs e) { - _display.DisplayMessageReceived(e); - _output.ConnectionMessageReceived(e); + _display!.DisplayMessageReceived(e); + _output!.ConnectionMessageReceived(e); } - private void SessionStarted(object sender, SessionEventArgs e) + private void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - private void SessionStopped(object sender, SessionEventArgs e) + private void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - private void Recognizing(object sender, IntentRecognitionEventArgs e) + private void Recognizing(object? sender, IntentRecognitionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayRecognizing(e); - _output.Recognizing(e); + _display!.DisplayRecognizing(e); + _output!.Recognizing(e); } - private void Recognized(object sender, IntentRecognitionEventArgs e) + private void Recognized(object? sender, IntentRecognitionEventArgs e) { - _display.DisplayRecognized(e); - _output.Recognized(e); + _display!.DisplayRecognized(e); + _output!.Recognized(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - private void Canceled(object sender, IntentRecognitionCanceledEventArgs e) + private void Canceled(object? sender, IntentRecognitionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } @@ -666,15 +664,15 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -686,22 +684,22 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } private bool _microphone = false; private bool _connect = false; private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectRecognized = 0; private int _expectSessionStopped = 0; private int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/meeting_transcription_command.cs b/src/extensions/speech_extension/commands/meeting_transcription_command.cs index 78776dc5..72cacb32 100644 --- a/src/extensions/speech_extension/commands/meeting_transcription_command.cs +++ b/src/extensions/speech_extension/commands/meeting_transcription_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class MeetingTranscriptionCommand : Command { - internal MeetingTranscriptionCommand(ICommandValues values) + internal MeetingTranscriptionCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } internal bool RunCommand() @@ -31,7 +30,7 @@ internal bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { switch (recognize) { @@ -83,7 +82,7 @@ private MeetingTranscriber CreateMeetingTranscriber() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(transcriber); - _output.EnsureCachePropertyCollection("recognizer", transcriber.Properties); + _output!.EnsureCachePropertyCollection("recognizer", transcriber.Properties); return transcriber; } @@ -105,7 +104,7 @@ private SpeechConfig CreateSpeechConfig() _values.AddThrowError("ERROR:", $"Creating SpeechConfig; use of region requires one of: key or token."); } - SpeechConfig config = null; + SpeechConfig? config = null; if (!string.IsNullOrEmpty(endpoint)) { config = string.IsNullOrEmpty(key) @@ -147,7 +146,7 @@ private void SetSpeechConfigProperties(SpeechConfig config) var endpointId = _values["service.config.endpoint.id"]; if (!string.IsNullOrEmpty(endpointId)) config.EndpointId = endpointId; - var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; var profanity = _values["service.output.config.profanity.option"]; @@ -164,10 +163,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); var rtf = _values.GetOrDefault("audio.input.real.time.factor", -1); @@ -176,10 +175,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var fastLane = _values.GetOrDefault("audio.input.fast.lane", rtf >= 0 ? 0 : -1); if (fastLane >= 0) config.SetProperty("SPEECH-TransmitLengthBeforThrottleMs", fastLane.ToString()); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); // config.SetProperty("AudioConfig_NumberOfChannelsForCapture", "8"); @@ -258,7 +257,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -279,7 +278,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -304,9 +303,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -320,14 +318,14 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } private KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -387,70 +385,70 @@ private void RecognizerConnectionConnect(Connection connection, bool continuous) private void RecognizerConnectionDisconnect(MeetingTranscriber transcriber) { - _lock.EnterReaderLockOnce(ref _expectDisconnected); + _lock!.EnterReaderLockOnce(ref _expectDisconnected); var connection = Connection.FromRecognizer(transcriber); connection.Close(); } - private void Connected(object sender, ConnectionEventArgs e) + private void Connected(object? sender, ConnectionEventArgs e) { - _display.DisplayConnected(e); - _output.Connected(e); + _display!.DisplayConnected(e); + _output!.Connected(e); } - private void Disconnected(object sender, ConnectionEventArgs e) + private void Disconnected(object? sender, ConnectionEventArgs e) { - _display.DisplayDisconnected(e); - _output.Disconnected(e); + _display!.DisplayDisconnected(e); + _output!.Disconnected(e); - _lock.ExitReaderLockOnce(ref _expectDisconnected); + _lock!.ExitReaderLockOnce(ref _expectDisconnected); } - private void ConnectionMessageReceived(object sender, ConnectionMessageEventArgs e) + private void ConnectionMessageReceived(object? sender, ConnectionMessageEventArgs e) { - _display.DisplayMessageReceived(e); - _output.ConnectionMessageReceived(e); + _display!.DisplayMessageReceived(e); + _output!.ConnectionMessageReceived(e); } - private void SessionStarted(object sender, SessionEventArgs e) + private void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - private void SessionStopped(object sender, SessionEventArgs e) + private void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - private void Transcribing(object sender, MeetingTranscriptionEventArgs e) + private void Transcribing(object? sender, MeetingTranscriptionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayTranscribing(e); - _output.Transcribing(e); + _display!.DisplayTranscribing(e); + _output!.Transcribing(e); } - private void Transcribed(object sender, MeetingTranscriptionEventArgs e) + private void Transcribed(object? sender, MeetingTranscriptionEventArgs e) { - _display.DisplayTranscribed(e); - _output.Transcribed(e); + _display!.DisplayTranscribed(e); + _output!.Transcribed(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - private void Canceled(object sender, MeetingTranscriptionCanceledEventArgs e) + private void Canceled(object? sender, MeetingTranscriptionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } @@ -479,15 +477,15 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -499,22 +497,22 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } private bool _microphone = false; private bool _connect = false; private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectRecognized = 0; private int _expectSessionStopped = 0; private int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/parsers/custom_speech_recognition_command_parser.cs b/src/extensions/speech_extension/commands/parsers/custom_speech_recognition_command_parser.cs index 0b01f831..2f342789 100644 --- a/src/extensions/speech_extension/commands/parsers/custom_speech_recognition_command_parser.cs +++ b/src/extensions/speech_extension/commands/parsers/custom_speech_recognition_command_parser.cs @@ -120,7 +120,8 @@ public static INamedValueTokenParser[] GetCommandParsers(ICommandValues values) } - return null; + values.AddThrowError("ERROR:", $"Unknown command: {commandName}"); + return Array.Empty(); } #region private data diff --git a/src/extensions/speech_extension/commands/parsers/dialog_command_parser.cs b/src/extensions/speech_extension/commands/parsers/dialog_command_parser.cs index 2931512e..d6f6b767 100644 --- a/src/extensions/speech_extension/commands/parsers/dialog_command_parser.cs +++ b/src/extensions/speech_extension/commands/parsers/dialog_command_parser.cs @@ -44,7 +44,8 @@ private static INamedValueTokenParser[] GetCommandParsers(ICommandValues values) return ccCommandParsers; } - return null; + values.AddThrowError("ERROR:", $"Unknown command: {commandName}"); + return Array.Empty(); } #region private data diff --git a/src/extensions/speech_extension/commands/parsers/webjob_command_parser.cs b/src/extensions/speech_extension/commands/parsers/webjob_command_parser.cs index f9967fef..220cdf0b 100644 --- a/src/extensions/speech_extension/commands/parsers/webjob_command_parser.cs +++ b/src/extensions/speech_extension/commands/parsers/webjob_command_parser.cs @@ -57,7 +57,8 @@ private static INamedValueTokenParser[] GetCommandParsers(ICommandValues values) return deleteCommandParsers; } - return null; + values.AddThrowError("ERROR:", $"Unknown command: {commandName}"); + return Array.Empty(); } #region private data diff --git a/src/extensions/speech_extension/commands/profile_command.cs b/src/extensions/speech_extension/commands/profile_command.cs index b5c62ac9..1ec5485a 100644 --- a/src/extensions/speech_extension/commands/profile_command.cs +++ b/src/extensions/speech_extension/commands/profile_command.cs @@ -20,9 +20,8 @@ namespace Azure.AI.Details.Common.CLI { public class ProfileCommand : Command { - public ProfileCommand(ICommandValues values) + public ProfileCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -116,8 +115,8 @@ private void DoCreateProfile() private void DoDeleteProfile() { - var profileId = _values.GetOrDefault("profile.id", ""); - var file = _values.GetOrDefault("profile.input.file", ""); + var profileId = _values.GetOrEmpty("profile.id"); + var file = _values.GetOrEmpty("profile.input.file"); if (string.IsNullOrEmpty(profileId) && string.IsNullOrEmpty(file)) { _values.AddThrowError( @@ -190,7 +189,7 @@ private List ParseArray(JsonElement[] array, string key) private void DoProfileStatus() { - var id = _values.GetOrDefault("profile.id", ""); + var id = _values.GetOrEmpty("profile.id"); if (string.IsNullOrEmpty(id)) { _values.AddThrowError( @@ -239,7 +238,7 @@ private VoiceProfileType GetVoiceProfileType() private void DoEnrollProfile() { - var id = _values.GetOrDefault("profile.id", ""); + var id = _values.GetOrEmpty("profile.id"); if (string.IsNullOrEmpty(id)) { _values.AddThrowError( @@ -276,7 +275,7 @@ private void DoEnrollProfile() private void Recognize(VoiceProfileType type = VoiceProfileType.TextIndependentVerification) { - var id = _values.GetOrDefault("profile.id", ""); + var id = _values.GetOrEmpty("profile.id"); RecognizeSpeaker(type, id); } @@ -389,7 +388,7 @@ private void CheckWriteOutputId(string id) { var idOk = !string.IsNullOrEmpty(id); - var atId = _values.GetOrDefault("profile.output.id", ""); + var atId = _values.GetOrEmpty("profile.output.id"); var atIdOk = !string.IsNullOrEmpty(atId); if (idOk && atIdOk) { @@ -397,7 +396,7 @@ private void CheckWriteOutputId(string id) FileHelpers.WriteAllText(atIdFile, id, Encoding.UTF8); } - var addId = _values.GetOrDefault("profile.output.add.id", ""); + var addId = _values.GetOrEmpty("profile.output.add.id"); var addIdOk = !string.IsNullOrEmpty(addId); if (idOk && addIdOk) { @@ -416,7 +415,7 @@ private string CheckWriteOutputSelf(string json, string key) private void CheckWriteOutputIds(string json, string key) { - var atIds = _values.GetOrDefault("profile.output.ids", ""); + var atIds = _values.GetOrEmpty("profile.output.ids"); var atIdsOk = !string.IsNullOrEmpty(atIds); var ids = atIdsOk ? new StringBuilder() : null; diff --git a/src/extensions/speech_extension/commands/recognize_command.cs b/src/extensions/speech_extension/commands/recognize_command.cs index 53315b4b..7940305f 100644 --- a/src/extensions/speech_extension/commands/recognize_command.cs +++ b/src/extensions/speech_extension/commands/recognize_command.cs @@ -19,9 +19,8 @@ namespace Azure.AI.Details.Common.CLI { public class RecognizeCommand : Command { - public RecognizeCommand(ICommandValues values) + public RecognizeCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } public bool RunCommand() @@ -30,7 +29,7 @@ public bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { switch (recognize) { @@ -151,7 +150,7 @@ private SpeechRecognizer CreateSpeechRecognizer() var config = CreateSpeechConfig(); var audioConfig = ConfigHelpers.CreateAudioConfig(_values); - CreateSourceLanguageConfig(config, out SourceLanguageConfig language, out AutoDetectSourceLanguageConfig autoDetect); + CreateSourceLanguageConfig(config, out var language, out var autoDetect); var recognizer = autoDetect != null ? new SpeechRecognizer(config, autoDetect, audioConfig) @@ -164,12 +163,12 @@ private SpeechRecognizer CreateSpeechRecognizer() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(recognizer); - _output.EnsureCachePropertyCollection("recognizer", recognizer.Properties); + _output!.EnsureCachePropertyCollection("recognizer", recognizer.Properties); return recognizer; } - private void CreateSourceLanguageConfig(SpeechConfig config, out SourceLanguageConfig language, out AutoDetectSourceLanguageConfig autoDetect) + private void CreateSourceLanguageConfig(SpeechConfig config, out SourceLanguageConfig? language, out AutoDetectSourceLanguageConfig? autoDetect) { language = null; autoDetect = null; @@ -198,7 +197,7 @@ private void CreateSourceLanguageConfig(SpeechConfig config, out SourceLanguageC } } - private SpeechConfig CreateSpeechConfig(string key=null, string region = null) + private SpeechConfig CreateSpeechConfig(string? key = null, string? region = null) { SpeechConfig config = ConfigHelpers.CreateSpeechConfig(_values, key, region); SetSpeechConfigProperties(config); @@ -213,10 +212,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var endpointId = _values["service.config.endpoint.id"]; if (!string.IsNullOrEmpty(endpointId)) config.EndpointId = endpointId; - var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; - var profanity = _values.GetOrDefault("service.output.config.profanity.option", "").ToLower(); + var profanity = _values.GetOrEmpty("service.output.config.profanity.option").ToLower(); if (profanity == "removed") config.SetProfanity(ProfanityOption.Removed); if (profanity == "masked") config.SetProfanity(ProfanityOption.Masked); if (profanity == "raw") config.SetProfanity(ProfanityOption.Raw); @@ -230,10 +229,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); var rtf = _values.GetOrDefault("audio.input.real.time.factor", -1); @@ -242,10 +241,10 @@ private void SetSpeechConfigProperties(SpeechConfig config) var fastLane = _values.GetOrDefault("audio.input.fast.lane", rtf >= 0 ? 0 : -1); if (fastLane >= 0) config.SetProperty("SPEECH-TransmitLengthBeforThrottleMs", fastLane.ToString()); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); var embedded = _values.GetOrDefault("embedded.config.embedded", false); @@ -259,10 +258,10 @@ private void SetEmbeddedProperties(SpeechConfig config) // Turn on embedded (offline) speech recognition. config.SetProperty("SPEECH-RecoBackend", "offline"); - var modelKey = _values.GetOrDefault("embedded.config.model.key", ""); + var modelKey = _values.GetOrEmpty("embedded.config.model.key"); config.SetProperty("SPEECH-RecoModelKey", modelKey); - var modelPath = _values.GetOrDefault("embedded.config.model.path", ""); + var modelPath = _values.GetOrEmpty("embedded.config.model.path"); var modelIniFileFullPath = Path.GetFullPath(Path.Combine(modelPath, "sr.ini")); if (!File.Exists(modelIniFileFullPath)) { @@ -330,7 +329,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -351,7 +350,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -376,9 +375,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -392,14 +390,14 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } private KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -459,70 +457,70 @@ private void RecognizerConnectionConnect(Connection connection, bool continuous) private void RecognizerConnectionDisconnect(SpeechRecognizer recognizer) { - _lock.EnterReaderLockOnce(ref _expectDisconnected); + _lock!.EnterReaderLockOnce(ref _expectDisconnected); var connection = Connection.FromRecognizer(recognizer); connection.Close(); } - private void Connected(object sender, ConnectionEventArgs e) + private void Connected(object? sender, ConnectionEventArgs e) { - _display.DisplayConnected(e); - _output.Connected(e); + _display!.DisplayConnected(e); + _output!.Connected(e); } - private void Disconnected(object sender, ConnectionEventArgs e) + private void Disconnected(object? sender, ConnectionEventArgs e) { - _display.DisplayDisconnected(e); - _output.Disconnected(e); + _display!.DisplayDisconnected(e); + _output!.Disconnected(e); - _lock.ExitReaderLockOnce(ref _expectDisconnected); + _lock!.ExitReaderLockOnce(ref _expectDisconnected); } - private void ConnectionMessageReceived(object sender, ConnectionMessageEventArgs e) + private void ConnectionMessageReceived(object? sender, ConnectionMessageEventArgs e) { - _display.DisplayMessageReceived(e); - _output.ConnectionMessageReceived(e); + _display!.DisplayMessageReceived(e); + _output!.ConnectionMessageReceived(e); } - private void SessionStarted(object sender, SessionEventArgs e) + private void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - private void SessionStopped(object sender, SessionEventArgs e) + private void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - private void Recognizing(object sender, SpeechRecognitionEventArgs e) + private void Recognizing(object? sender, SpeechRecognitionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayRecognizing(e); - _output.Recognizing(e); + _display!.DisplayRecognizing(e); + _output!.Recognizing(e); } - private void Recognized(object sender, SpeechRecognitionEventArgs e) + private void Recognized(object? sender, SpeechRecognitionEventArgs e) { - _display.DisplayRecognized(e); - _output.Recognized(e); + _display!.DisplayRecognized(e); + _output!.Recognized(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - private void Canceled(object sender, SpeechRecognitionCanceledEventArgs e) + private void Canceled(object? sender, SpeechRecognitionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } @@ -583,15 +581,15 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -603,22 +601,22 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } private bool _microphone = false; private bool _connect = false; private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectRecognized = 0; private int _expectSessionStopped = 0; private int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/synthesize_command.cs b/src/extensions/speech_extension/commands/synthesize_command.cs index f99c3a11..6f85bdc7 100644 --- a/src/extensions/speech_extension/commands/synthesize_command.cs +++ b/src/extensions/speech_extension/commands/synthesize_command.cs @@ -19,9 +19,8 @@ namespace Azure.AI.Details.Common.CLI { public class SynthesizeCommand : Command { - public SynthesizeCommand(ICommandValues values) + public SynthesizeCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } public bool RunCommand() @@ -134,13 +133,13 @@ private void SynthesizeInteractive(bool repeatedly = false) private void SynthesizeText() { - var text = _values.GetOrDefault("synthesizer.input.text", ""); + var text = _values.GetOrEmpty("synthesizer.input.text"); SynthesizeText(text); } private void SynthesizeTextFile() { - var fileName = _values.GetOrDefault("synthesizer.input.text.file", ""); + var fileName = _values.GetOrEmpty("synthesizer.input.text.file"); var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "text input"); var text = FileHelpers.ReadAllText(existing, Encoding.Default); SynthesizeText(text); @@ -166,13 +165,13 @@ private void SynthesizeText(string text) private void SynthesizeSsml() { - var ssml = _values.GetOrDefault("synthesizer.input.ssml", ""); + var ssml = _values.GetOrEmpty("synthesizer.input.ssml"); SynthesizeSsml(ssml); } private void SynthesizeSsmlFile() { - var fileName = _values.GetOrDefault("synthesizer.input.ssml.file", _values.GetOrDefault("synthesizer.input.text.file", "")); + var fileName = _values.GetOrDefault("synthesizer.input.ssml.file", _values.GetOrEmpty("synthesizer.input.text.file")); var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "ssml input"); var content = FileHelpers.ReadAllText(existing, Encoding.Default); @@ -217,7 +216,7 @@ private SpeechSynthesizer CreateSpeechSynthesizer() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(synthesizer); - // _output.EnsureCachePropertyCollection("synthesizer", synthesizer.Properties); + // _output!.EnsureCachePropertyCollection("synthesizer", synthesizer.Properties); return synthesizer; } @@ -245,7 +244,7 @@ private SpeechConfig CreateSpeechConfig() _values.AddThrowError("ERROR:", $"Creating SpeechConfig; use of region requires one of: key or token."); } - SpeechConfig config = null; + SpeechConfig? config = null; if (!string.IsNullOrEmpty(endpoint)) { config = string.IsNullOrEmpty(key) @@ -293,7 +292,7 @@ private void SetSpeechConfigProperties(SpeechConfig config) var endpointId = _values["service.config.endpoint.id"]; if (!string.IsNullOrEmpty(endpointId)) config.EndpointId = endpointId; - // var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + // var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); // if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; // var profanity = _values["service.output.config.profanity.option"]; @@ -307,16 +306,16 @@ private void SetSpeechConfigProperties(SpeechConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); var embedded = _values.GetOrDefault("embedded.config.embedded", false); @@ -332,10 +331,10 @@ private void SetEmbeddedProperties(SpeechConfig config) // The device neural voices only support 24kHz and the offline engine has no ability to resample config.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Riff24Khz16BitMonoPcm); - var modelKey = _values.GetOrDefault("embedded.config.model.key", ""); + var modelKey = _values.GetOrEmpty("embedded.config.model.key"); config.SetProperty("SPEECH-SynthesisModelKey", modelKey); - var modelPath = _values.GetOrDefault("embedded.config.model.path", ""); + var modelPath = _values.GetOrEmpty("embedded.config.model.path"); var modelXmlFileFullPath = Path.GetFullPath(Path.Combine(modelPath, "Tokens.xml")); if (!File.Exists(modelXmlFileFullPath)) { @@ -376,7 +375,7 @@ private void CheckSynthesizerInput() var fileValueDisplayName = _values.Contains("synthesizer.input.text.file") ? "text file" : "ssml file"; var fileValueName = _values.Contains("synthesizer.input.text.file") ? "synthesizer.input.text.file" : "synthesizer.input.ssml.file"; - var file = _values.GetOrDefault(fileValueName, ""); + var file = _values.GetOrEmpty(fileValueName); var url = ""; if (!string.IsNullOrEmpty(file) && file.StartsWith("http")) @@ -480,7 +479,7 @@ private string GetInputFileFromId(string id) return file; } - private AudioConfig CreateAudioConfig() + private AudioConfig? CreateAudioConfig() { var output = _values["audio.output.type"]; var file = _values["audio.output.file"]; @@ -503,41 +502,41 @@ private AudioConfig CreateAudioConfig() return audioConfig; } - private void SynthesisStarted(object sender, SpeechSynthesisEventArgs e) + private void SynthesisStarted(object? sender, SpeechSynthesisEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSynthesisCompleted); + _lock!.EnterReaderLockOnce(ref _expectSynthesisCompleted); _stopEvent.Reset(); - _display.DisplaySynthesisStarted(e); - _output.SynthesisStarted(e); + _display!.DisplaySynthesisStarted(e); + _output!.SynthesisStarted(e); } - private void Synthesizing(object sender, SpeechSynthesisEventArgs e) + private void Synthesizing(object? sender, SpeechSynthesisEventArgs e) { - _display.DisplaySynthesizing(e); - _output.Synthesizing(e); + _display!.DisplaySynthesizing(e); + _output!.Synthesizing(e); } - private void SynthesisCompleted(object sender, SpeechSynthesisEventArgs e) + private void SynthesisCompleted(object? sender, SpeechSynthesisEventArgs e) { - _display.DisplaySynthesisCompleted(e); - _output.SynthesisCompleted(e); + _display!.DisplaySynthesisCompleted(e); + _output!.SynthesisCompleted(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSynthesisCompleted); + _lock!.ExitReaderLockOnce(ref _expectSynthesisCompleted); } - private void SynthesisCanceled(object sender, SpeechSynthesisEventArgs e) + private void SynthesisCanceled(object? sender, SpeechSynthesisEventArgs e) { - _display.DisplaySynthesisCanceled(e); - _output.SynthesisCanceled(e); + _display!.DisplaySynthesisCanceled(e); + _output!.SynthesisCanceled(e); _canceledEvent.Set(); } - private void SynthesisWordBoundary(object sender, SpeechSynthesisWordBoundaryEventArgs e) + private void SynthesisWordBoundary(object? sender, SpeechSynthesisWordBoundaryEventArgs e) { - _display.DisplaySynthesisWordBoundary(e); - _output.SynthesisWordBoundary(e); + _display!.DisplaySynthesisWordBoundary(e); + _output!.SynthesisWordBoundary(e); } private void WaitForStopOrCancel(SpeechSynthesizer synthesizer, Task task) @@ -559,11 +558,11 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); var id = _values["synthesizer.input.id"]; - _output.EnsureOutputAll("synthesizer.input.id", id); - _output.EnsureOutputEach("synthesizer.input.id", id); + _output!.EnsureOutputAll("synthesizer.input.id", id); + _output!.EnsureOutputEach("synthesizer.input.id", id); _lock = new SpinLock(); _lock.StartLock(); @@ -573,16 +572,16 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectSynthesisCompleted = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/translate_command.cs b/src/extensions/speech_extension/commands/translate_command.cs index badcee67..9cba3eee 100644 --- a/src/extensions/speech_extension/commands/translate_command.cs +++ b/src/extensions/speech_extension/commands/translate_command.cs @@ -19,9 +19,8 @@ namespace Azure.AI.Details.Common.CLI { public class TranslateCommand : Command { - public TranslateCommand(ICommandValues values) + public TranslateCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); } public bool RunCommand() @@ -30,7 +29,7 @@ public bool RunCommand() return _values.GetOrDefault("passed", true); } - private void Recognize(string recognize) + private void Recognize(string? recognize) { switch (recognize) { @@ -170,7 +169,7 @@ private TranslationRecognizer CreateTranslationRecognizer() _disposeAfterStop.Add(audioConfig); _disposeAfterStop.Add(recognizer); - _output.EnsureCachePropertyCollection("recognizer", recognizer.Properties); + _output!.EnsureCachePropertyCollection("recognizer", recognizer.Properties); return recognizer; } @@ -272,7 +271,7 @@ private void SetTranslationConfigProperties(SpeechTranslationConfig config) var categoryId = _values["service.config.category.id"]; if (!string.IsNullOrEmpty(categoryId)) config.SetServiceProperty("categoryId", categoryId, ServicePropertyChannel.UriQueryParameter); - var needDetailedText = _output.NeedsLexicalText() || _output.NeedsItnText(); + var needDetailedText = _output != null && (_output.NeedsLexicalText() || _output.NeedsItnText()); if (needDetailedText) config.OutputFormat = OutputFormat.Detailed; var profanity = _values["service.output.config.profanity.option"]; @@ -289,10 +288,10 @@ private void SetTranslationConfigProperties(SpeechTranslationConfig config) var trafficType = _values.GetOrDefault("service.config.endpoint.traffic.type", "spx"); config.SetServiceProperty("traffictype", trafficType, ServicePropertyChannel.UriQueryParameter); - var endpointParam = _values.GetOrDefault("service.config.endpoint.query.string", ""); + var endpointParam = _values.GetOrEmpty("service.config.endpoint.query.string"); if (!string.IsNullOrEmpty(endpointParam)) ConfigHelpers.SetEndpointParams(config, endpointParam); - var httpHeader = _values.GetOrDefault("service.config.endpoint.http.header", ""); + var httpHeader = _values.GetOrEmpty("service.config.endpoint.http.header"); if (!string.IsNullOrEmpty(httpHeader)) SetHttpHeaderProperty(config, httpHeader); var rtf = _values.GetOrDefault("audio.input.real.time.factor", -1); @@ -301,10 +300,10 @@ private void SetTranslationConfigProperties(SpeechTranslationConfig config) var fastLane = _values.GetOrDefault("audio.input.fast.lane", rtf >= 0 ? 0 : -1); if (fastLane >= 0) config.SetProperty("SPEECH-TransmitLengthBeforThrottleMs", fastLane.ToString()); - var stringProperty = _values.GetOrDefault("config.string.property", ""); + var stringProperty = _values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = _values.GetOrDefault("config.string.properties", ""); + var stringProperties = _values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); CheckNotYetImplementedConfigProperties(); @@ -368,7 +367,7 @@ private void CheckAudioInput() _microphone = (input == "microphone" || string.IsNullOrEmpty(input)); } - private string GetIdFromAudioInputFile(string input, string file) + private string GetIdFromAudioInputFile(string? input, string file) { string id; if (input == "microphone" || string.IsNullOrEmpty(input)) @@ -389,7 +388,7 @@ private string GetIdFromAudioInputFile(string input, string file) return id; } - private string GetAudioInputFromId(string id) + private string? GetAudioInputFromId(string id) { string input; if (id == "microphone") @@ -414,9 +413,8 @@ private string GetAudioInputFromId(string id) return input; } - private string GetAudioInputFileFromId(string id) + private string? GetAudioInputFileFromId(string id) { - string file; var existing = FileHelpers.FindFileInDataPath(id, _values); if (existing == null) existing = FileHelpers.FindFileInDataPath(id + ".wav", _values); @@ -430,14 +428,14 @@ private string GetAudioInputFileFromId(string id) } } - file = existing; + var file = existing; _values.Add("audio.input.file", file); return file; } private KeywordRecognitionModel LoadKeywordModel() { - var fileName = _values["recognize.keyword.file"]; + var fileName = _values["recognize.keyword.file"]!; var existing = FileHelpers.DemandFindFileInDataPath(fileName, _values, "keyword model"); var keywordModel = KeywordRecognitionModel.FromFile(existing); @@ -497,70 +495,70 @@ private void RecognizerConnectionConnect(Connection connection, bool continuous) private void RecognizerConnectionDisconnect(TranslationRecognizer recognizer) { - _lock.EnterReaderLockOnce(ref _expectDisconnected); + _lock!.EnterReaderLockOnce(ref _expectDisconnected); var connection = Connection.FromRecognizer(recognizer); connection.Close(); } - private void Connected(object sender, ConnectionEventArgs e) + private void Connected(object? sender, ConnectionEventArgs e) { - _display.DisplayConnected(e); - _output.Connected(e); + _display!.DisplayConnected(e); + _output!.Connected(e); } - private void Disconnected(object sender, ConnectionEventArgs e) + private void Disconnected(object? sender, ConnectionEventArgs e) { - _display.DisplayDisconnected(e); - _output.Disconnected(e); + _display!.DisplayDisconnected(e); + _output!.Disconnected(e); - _lock.ExitReaderLockOnce(ref _expectDisconnected); + _lock!.ExitReaderLockOnce(ref _expectDisconnected); } - private void ConnectionMessageReceived(object sender, ConnectionMessageEventArgs e) + private void ConnectionMessageReceived(object? sender, ConnectionMessageEventArgs e) { - _display.DisplayMessageReceived(e); - _output.ConnectionMessageReceived(e); + _display!.DisplayMessageReceived(e); + _output!.ConnectionMessageReceived(e); } - private void SessionStarted(object sender, SessionEventArgs e) + private void SessionStarted(object? sender, SessionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectSessionStopped); + _lock!.EnterReaderLockOnce(ref _expectSessionStopped); _stopEvent.Reset(); - _display.DisplaySessionStarted(e); - _output.SessionStarted(e); + _display!.DisplaySessionStarted(e); + _output!.SessionStarted(e); } - private void SessionStopped(object sender, SessionEventArgs e) + private void SessionStopped(object? sender, SessionEventArgs e) { - _display.DisplaySessionStopped(e); - _output.SessionStopped(e); + _display!.DisplaySessionStopped(e); + _output!.SessionStopped(e); _stopEvent.Set(); - _lock.ExitReaderLockOnce(ref _expectSessionStopped); + _lock!.ExitReaderLockOnce(ref _expectSessionStopped); } - private void Recognizing(object sender, TranslationRecognitionEventArgs e) + private void Recognizing(object? sender, TranslationRecognitionEventArgs e) { - _lock.EnterReaderLockOnce(ref _expectRecognized); + _lock!.EnterReaderLockOnce(ref _expectRecognized); - _display.DisplayRecognizing(e); - _output.Recognizing(e); + _display!.DisplayRecognizing(e); + _output!.Recognizing(e); } - private void Recognized(object sender, TranslationRecognitionEventArgs e) + private void Recognized(object? sender, TranslationRecognitionEventArgs e) { - _display.DisplayRecognized(e); - _output.Recognized(e); + _display!.DisplayRecognized(e); + _output!.Recognized(e); - _lock.ExitReaderLockOnce(ref _expectRecognized); + _lock!.ExitReaderLockOnce(ref _expectRecognized); } - private void Canceled(object sender, TranslationRecognitionCanceledEventArgs e) + private void Canceled(object? sender, TranslationRecognitionCanceledEventArgs e) { - _display.DisplayCanceled(e); - _output.Canceled(e); + _display!.DisplayCanceled(e); + _output!.Canceled(e); _canceledEvent.Set(); } @@ -621,15 +619,15 @@ private void StartCommand() _display = new DisplayHelper(_values); _output = new OutputHelper(_values); - _output.StartOutput(); + _output!.StartOutput(); - var id = _values["audio.input.id"]; - _output.EnsureOutputAll("audio.input.id", id); - _output.EnsureOutputEach("audio.input.id", id); - _output.EnsureCacheProperty("audio.input.id", id); + var id = _values["audio.input.id"]!; + _output!.EnsureOutputAll("audio.input.id", id); + _output!.EnsureOutputEach("audio.input.id", id); + _output!.EnsureCacheProperty("audio.input.id", id); var file = _values["audio.input.file"]; - _output.EnsureCacheProperty("audio.input.file", file); + _output!.EnsureCacheProperty("audio.input.file", file); _lock = new SpinLock(); _lock.StartLock(); @@ -641,22 +639,22 @@ private void StartCommand() private void StopCommand() { - _lock.StopLock(5000); + _lock!.StopLock(5000); - _output.CheckOutput(); - _output.StopOutput(); + _output!.CheckOutput(); + _output!.StopOutput(); } private bool _microphone = false; private bool _connect = false; private bool _disconnect = false; - private SpinLock _lock = null; + private SpinLock? _lock = null; private int _expectRecognized = 0; private int _expectSessionStopped = 0; private int _expectDisconnected = 0; - OutputHelper _output = null; - DisplayHelper _display = null; + OutputHelper? _output = null; + DisplayHelper? _display = null; } } diff --git a/src/extensions/speech_extension/commands/webjob_command.cs b/src/extensions/speech_extension/commands/webjob_command.cs index 501a6db3..006fb5b7 100644 --- a/src/extensions/speech_extension/commands/webjob_command.cs +++ b/src/extensions/speech_extension/commands/webjob_command.cs @@ -19,9 +19,8 @@ namespace Azure.AI.Details.Common.CLI { public class WebJobCommand : Command { - internal WebJobCommand(ICommandValues values) + internal WebJobCommand(ICommandValues values) : base(values) { - _values = values.ReplaceValues(); _quiet = _values.GetOrDefault("x.quiet", false); _verbose = _values.GetOrDefault("x.verbose", true); } @@ -164,7 +163,7 @@ private void DoRun(string name = "") /// --output request FILE/- /// --output json FILE/- /// - private void DoStatus(string name = null, string id = null) + private void DoStatus(string? name = null, string? id = null) { GetStatusParameters(out string path, ref name, out string nameAction, ref id, out string message); @@ -224,7 +223,7 @@ private void DoStatus(string name = null, string id = null) /// --output request FILE/- /// --output file FILE/- /// - private string DoDownload() + private string? DoDownload() { GetDownloadParameters(out string url, out string message); @@ -266,8 +265,8 @@ private void DoDelete() private void GetListParameters(out string path, out string name, out string nameAction, out string id, out string message, out string arrayName, out string urlName, out IdKind kind) { - name = _values.GetOrDefault("webjob.job.name", ""); - id = _values.GetOrDefault("webjob.job.id", ""); + name = _values.GetOrEmpty("webjob.job.name"); + id = _values.GetOrEmpty("webjob.job.id"); var nameOk = !string.IsNullOrEmpty(name); var idOk = nameOk && !string.IsNullOrEmpty(id); @@ -300,8 +299,8 @@ private void GetUploadParameters(out string message, out string path, out string message = "Uploading webjob ..."; path = $"api/triggeredwebjobs"; - jobName = _values.GetOrDefault("webjob.job.name", ""); - fileName = _values.GetOrDefault("webjob.upload.job.file", ""); + jobName = _values.GetOrEmpty("webjob.job.name"); + fileName = _values.GetOrEmpty("webjob.upload.job.file"); fileName = FileHelpers.DemandFindFileInDataPath(fileName, _values, "webjob upload"); var fileNameOk = !string.IsNullOrEmpty(fileName); @@ -340,7 +339,7 @@ private void GetStatusParameters(out string path, ref string name, out string na private void GetDownloadParameters(out string url, out string message) { - var jobid = _values.GetOrDefault("webjob.job.id", ""); + var jobid = _values.GetOrEmpty("webjob.job.id"); if (!StringHelpers.SplitNameValue(jobid, out string job, out string id)) { job = ""; @@ -354,7 +353,7 @@ private void GetDownloadParameters(out string url, out string message) id = ""; } - var file = _values.GetOrDefault("webjob.download.file", ""); + var file = _values.GetOrEmpty("webjob.download.file"); if (string.IsNullOrEmpty(file)) { file = "."; @@ -384,7 +383,7 @@ private void GetDeleteParameters(out string path, out string name, out string na path = $"api/triggeredwebjobs"; } - private string DemandWebJobName(string name = null) + private string DemandWebJobName(string? name = null) { return _values.DemandGetOrDefault("webjob.job.name", name, ErrorHelpers.CreateMessage( @@ -392,7 +391,7 @@ private string DemandWebJobName(string name = null) "USE:", $"{Program.Name} webjob [...] --name NAME")); } - private string DemandWebJobId(string id = null) + private string DemandWebJobId(string? id = null) { return _values.DemandGetOrDefault("webjob.job.id", id, ErrorHelpers.CreateMessage( @@ -400,11 +399,11 @@ private string DemandWebJobId(string id = null) "USE:", $"{Program.Name} webjob [...] --id ID")); } - private HttpWebRequest CreateWebRequest(string method, string path, string name = null, string nameAction = null, string id = null, string contentType = null) + private HttpWebRequest CreateWebRequest(string method, string path, string? name = null, string nameAction = null, string? id = null, string? contentType = null) { - var endpoint = _values.GetOrDefault("webjob.config.endpoint", "").Trim('\r', '\n'); - var userName = _values.GetOrDefault("webjob.config.username", "").Trim('\r', '\n'); - var password = _values.GetOrDefault("webjob.config.password", "").Trim('\r', '\n'); + var endpoint = _values.GetOrEmpty("webjob.config.endpoint").Trim('\r', '\n'); + var userName = _values.GetOrEmpty("webjob.config.username").Trim('\r', '\n'); + var password = _values.GetOrEmpty("webjob.config.password").Trim('\r', '\n'); var timeout = _values.GetOrDefault("webjob.timeout", 100000); if (string.IsNullOrEmpty(endpoint) || string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password)) @@ -429,7 +428,7 @@ private HttpWebRequest CreateWebRequest(string method, string path, string name return request; } - private string GetWebJobUrl(string endpoint, string path, string name = null, string nameAction = null, string id = null) + private string GetWebJobUrl(string endpoint, string path, string? name = null, string nameAction = null, string? id = null) { if (path.StartsWith("http")) return path; @@ -453,7 +452,7 @@ private string GetWebJobUrl(string endpoint, string path, string name = null, st private string CheckWriteOutputRequest(HttpWebRequest request, string payload = null, bool append = false) { - var output = _values.GetOrDefault("webjob.output.request.file", ""); + var output = _values.GetOrEmpty("webjob.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); @@ -464,7 +463,7 @@ private string CheckWriteOutputRequest(HttpWebRequest request, string payload = private byte[] CheckWriteOutputRequest(HttpWebRequest request, byte[] payload) { - var output = _values.GetOrDefault("webjob.output.request.file", ""); + var output = _values.GetOrEmpty("webjob.output.request.file"); if (!string.IsNullOrEmpty(output)) { var fileName = FileHelpers.GetOutputDataFileName(output, _values); @@ -480,7 +479,7 @@ private string ReadWritePrintJson(HttpWebResponse response) return json; } - private string ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) + private string? ReadWritePrintResponse(HttpWebResponse response, string defaultFileName = null) { var saveAs = HttpHelpers.GetOutputDataFileName(defaultFileName, response, _values, "webjob", out bool isText, out bool isJson); diff --git a/src/extensions/speech_extension/helpers/audio_helpers.cs b/src/extensions/speech_extension/helpers/audio_helpers.cs index a39babbd..96f90df7 100644 --- a/src/extensions/speech_extension/helpers/audio_helpers.cs +++ b/src/extensions/speech_extension/helpers/audio_helpers.cs @@ -18,7 +18,12 @@ namespace Azure.AI.Details.Common.CLI { public class AudioHelpers : Command { - public static AudioConfig CreateAudioConfigFromFile(string file, string format) + public AudioHelpers(ICommandValues values) : base(values) + { + // weird that this is a command... it's never instantiated + } + + public static AudioConfig CreateAudioConfigFromFile(string file, string? format) { return !string.IsNullOrEmpty(format) ? AudioConfig.FromStreamInput(CreatePushStream(file, format)) @@ -27,7 +32,7 @@ public static AudioConfig CreateAudioConfigFromFile(string file, string format) : AudioConfig.FromWavFileInput(file); } - public static AudioConfig CreateMicrophoneAudioConfig(string device) + public static AudioConfig CreateMicrophoneAudioConfig(string? device) { return !string.IsNullOrEmpty(device) ? AudioConfig.FromMicrophoneInput(device) @@ -80,6 +85,11 @@ static public PushAudioInputStream CreatePushStream(string file) public class AudioOutputHelpers : Command { + public AudioOutputHelpers(ICommandValues values) : base(values) + { + // weird that this is a command... it's never instantiated + } + public static AudioConfig CreateAudioConfigForFile(string file) { return FileHelpers.IsStandardOutputReference(file) @@ -87,7 +97,7 @@ public static AudioConfig CreateAudioConfigForFile(string file) : AudioConfig.FromWavFileOutput(file); } - public static AudioConfig CreateAudioConfigForSpeaker(string device = null) + public static AudioConfig CreateAudioConfigForSpeaker(string? device = null) { return !string.IsNullOrEmpty(device) ? AudioConfig.FromSpeakerOutput(device) diff --git a/src/extensions/speech_extension/helpers/caption_helper.cs b/src/extensions/speech_extension/helpers/caption_helper.cs index bd86162f..d6ec0034 100644 --- a/src/extensions/speech_extension/helpers/caption_helper.cs +++ b/src/extensions/speech_extension/helpers/caption_helper.cs @@ -29,13 +29,13 @@ public struct Caption public class CaptionHelper { - public static IEnumerable GetCaptions(string language, int maxWidth, int maxHeight, IEnumerable results) + public static IEnumerable GetCaptions(string? language, int maxWidth, int maxHeight, IEnumerable results) { var helper = new CaptionHelper(language, maxWidth, maxHeight, results); return helper.GetCaptions(); } - public CaptionHelper(string language, int maxWidth, int maxHeight, IEnumerable results) + public CaptionHelper(string? language, int maxWidth, int maxHeight, IEnumerable results) { this._language = language; @@ -65,7 +65,7 @@ public CaptionHelper(string language, int maxWidth, int maxHeight, IEnumerable GetCaptions() { EnsureCaptions(); - return _captions; + return _captions!; } private void EnsureCaptions() @@ -90,7 +90,7 @@ private void AddCaptionsForAllResults() } } - private string GetTextOrTranslation(RecognitionResult result) + private string? GetTextOrTranslation(RecognitionResult result) { if (_language == null) return result.Text; @@ -122,7 +122,7 @@ private void AddCaptionsForFinalResult(RecognitionResult result, string text) var captionText = string.Join('\n', captionLines.ToArray()); captionLines.Clear(); - var captionSequence = _captions.Count + 1; + var captionSequence = _captions!.Count + 1; var isFirstCaption = captionStartsAt == 0; (var captionBegin, var captionEnd) = isFirstCaption && isLastCaption @@ -212,13 +212,13 @@ private int SkipSkippable(string text, int startIndex) private static bool IsFinalResult(object result) { - RecognitionResult final = result as RecognitionResult; + var final = result as RecognitionResult; return final?.Reason == ResultReason.RecognizedSpeech || final?.Reason == ResultReason.RecognizedIntent || final?.Reason == ResultReason.TranslatedSpeech; } - private readonly string _language; + private readonly string? _language; private readonly string[] _firstPassTerminators; private readonly string[] _secondPassTerminators; @@ -226,6 +226,6 @@ private static bool IsFinalResult(object result) private readonly int _maxHeight; private readonly IEnumerable _results; - private List _captions; + private List? _captions; } } diff --git a/src/extensions/speech_extension/helpers/config_helpers.cs b/src/extensions/speech_extension/helpers/config_helpers.cs index 06c7d6db..47251ec0 100644 --- a/src/extensions/speech_extension/helpers/config_helpers.cs +++ b/src/extensions/speech_extension/helpers/config_helpers.cs @@ -14,7 +14,7 @@ namespace Azure.AI.Details.Common.CLI { class ConfigHelpers { - public static SpeechConfig CreateSpeechConfig(ICommandValues values, string key=null, string region = null) + public static SpeechConfig CreateSpeechConfig(ICommandValues values, string? key = null, string? region = null) { key = string.IsNullOrEmpty(key) ? values["service.config.key"] : key; region = string.IsNullOrEmpty(region) ? values["service.config.region"] : region; @@ -64,16 +64,16 @@ public static SpeechConfig CreateSpeechConfig(ICommandValues values, string key= SetupLogFile(config, values); - var stringProperty = values.GetOrDefault("config.string.property", ""); + var stringProperty = values.GetOrEmpty("config.string.property"); if (!string.IsNullOrEmpty(stringProperty)) ConfigHelpers.SetStringProperty(config, stringProperty); - var stringProperties = values.GetOrDefault("config.string.properties", ""); + var stringProperties = values.GetOrEmpty("config.string.properties"); if (!string.IsNullOrEmpty(stringProperties)) ConfigHelpers.SetStringProperties(config, stringProperties); return config; } - public static AudioConfig CreateAudioConfig(ICommandValues values) + public static AudioConfig? CreateAudioConfig(ICommandValues values) { var input = values["audio.input.type"]; var file = values["audio.input.file"]; @@ -138,7 +138,7 @@ public static void SetupLogFile(SpeechConfig config, ICommandValues values) var log = values["diagnostics.config.log.file"]; if (!string.IsNullOrEmpty(log)) { - var id = values.GetOrDefault("audio.input.id", ""); + var id = values.GetOrEmpty("audio.input.id"); if (log.Contains("{id}")) log = log.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -147,7 +147,7 @@ public static void SetupLogFile(SpeechConfig config, ICommandValues values) var time = DateTime.Now.ToFileTime().ToString(); if (log.Contains("{time}")) log = log.Replace("{time}", time); - var runTime = values.GetOrDefault("x.run.time", ""); + var runTime = values.GetOrEmpty("x.run.time"); if (log.Contains("{run.time}")) log = log.Replace("{run.time}", runTime); log = FileHelpers.GetOutputDataFileName(log, values); diff --git a/src/extensions/speech_extension/helpers/connection_helpers.cs b/src/extensions/speech_extension/helpers/connection_helpers.cs index 137080e3..ef82520a 100644 --- a/src/extensions/speech_extension/helpers/connection_helpers.cs +++ b/src/extensions/speech_extension/helpers/connection_helpers.cs @@ -20,11 +20,11 @@ public static void SetConnectionMessageProperties(Connection connection, IComman SetConnectionMessageProperty(connection, "speech.context", uspContext); } - private static void SetConnectionMessageProperty(Connection connection, string msg, string property) + private static void SetConnectionMessageProperty(Connection connection, string msg, string? property) { if (IsJson(property)) { - SetConnectionMessagePropertyJson(connection, msg, property); + SetConnectionMessagePropertyJson(connection, msg, property!); } else if (!string.IsNullOrEmpty(property)) { @@ -55,7 +55,7 @@ private static void SetConnectionMessagePropertyNameValue(Connection connection, } } - private static bool IsJson(string json) + private static bool IsJson(string? json) { if (!string.IsNullOrEmpty(json)) { diff --git a/src/extensions/speech_extension/helpers/output_helper.cs b/src/extensions/speech_extension/helpers/output_helper.cs index 525b2e04..b9ac7829 100644 --- a/src/extensions/speech_extension/helpers/output_helper.cs +++ b/src/extensions/speech_extension/helpers/output_helper.cs @@ -56,7 +56,7 @@ public void StartOutput() _cacheResults = _values.Names.Any(s => s.StartsWith("check.result")) || _values.Names.Any(s => s.StartsWith("check.jmes")); - var source = _values.GetOrDefault("source.language.config", "en-US").Split(';')[0]; + var source = _values.GetOrDefault("source.language.config", "en-US")!.Split(';')[0]; _sourceCulture = new System.Globalization.CultureInfo(source); var target = _values.GetOrDefault("target.language.config", source); @@ -76,189 +76,189 @@ public void StopOutput() FlushOutputAllCache(); FlushOutputResultCache(); FlushOutputZipFile(); - _lock.StopLock(); + _lock!.StopLock(); } } public void Connected(ConnectionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputConnected(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Disconnected(ConnectionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputDisconnected(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void ConnectionMessageReceived(ConnectionMessageEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputConnectionMessageReceived(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SessionStarted(SessionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSessionStarted(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SessionStopped(SessionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSessionStopped(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognizing(SpeechRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognizing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognized(SpeechRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognized(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Canceled(SpeechRecognitionCanceledEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognizing(IntentRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognizing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognized(IntentRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognized(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Canceled(IntentRecognitionCanceledEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Transcribing(MeetingTranscriptionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputTranscribing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Transcribed(MeetingTranscriptionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputTranscribed(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Canceled(MeetingTranscriptionCanceledEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Transcribing(ConversationTranscriptionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputTranscribing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Transcribed(ConversationTranscriptionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputTranscribed(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Canceled(ConversationTranscriptionCanceledEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognizing(TranslationRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognizing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Recognized(TranslationRecognitionEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputRecognized(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Canceled(TranslationRecognitionCanceledEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SynthesisStarted(SpeechSynthesisEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSynthesisStarted(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void Synthesizing(SpeechSynthesisEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSynthesizing(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SynthesisCompleted(SpeechSynthesisEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSynthesisCompleted(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SynthesisCanceled(SpeechSynthesisEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputSynthesisCanceled(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void SynthesisWordBoundary(SpeechSynthesisWordBoundaryEventArgs e) { - _lock.EnterReaderLock(); + _lock!.EnterReaderLock(); OutputWordBoundary(e); - _lock.ExitReaderLock(); + _lock!.ExitReaderLock(); } public void EnsureCachePropertyCollection(string name, PropertyCollection properties) { EnsureInitPropertyCollectionCache(); - _propertyCollectionCache[name] = properties; + _propertyCollectionCache![name] = properties; } private void EnsureInitPropertyCollectionCache() @@ -269,10 +269,10 @@ private void EnsureInitPropertyCollectionCache() } } - private PropertyCollection GetPropertyCollection(string name) + private PropertyCollection? GetPropertyCollection(string name) { EnsureInitPropertyCollectionCache(); - return _propertyCollectionCache.ContainsKey(name) + return _propertyCollectionCache!.ContainsKey(name) ? _propertyCollectionCache[name] : null; } @@ -282,9 +282,9 @@ private bool ShouldCacheProperty() return _outputBatch; } - public void EnsureCacheProperty(string name, string value) + public void EnsureCacheProperty(string name, string? value) { - if (ShouldCacheProperty()) CacheProperty(name, value); + if (ShouldCacheProperty() && value != null) CacheProperty(name, value); } private bool ShouldCacheOutputResult() @@ -325,43 +325,43 @@ private void EnsureCacheOutputResult(SpeechSynthesisResult result) private void CacheProperty(string name, string value) { EnsureInitOutputResultCache(); - _propertyCache.Add(name, value); + _propertyCache!.Add(name, value); } private void CacheOutputResult(SpeechRecognitionResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void CacheOutputResult(IntentRecognitionResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void CacheOutputResult(MeetingTranscriptionResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void CacheOutputResult(ConversationTranscriptionResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void CacheOutputResult(TranslationRecognitionResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void CacheOutputResult(SpeechSynthesisResult result) { EnsureInitOutputResultCache(); - _outputResultCache.Add(result); + _outputResultCache!.Add(result); } private void EnsureInitOutputResultCache() @@ -389,9 +389,9 @@ private void FlushOutputResultCache() private string GetOutputBatchFileName() { - var file = _values.GetOrDefault("output.batch.file.name", "output.{id}.{run.time}.json"); + var file = _values.GetOrDefault("output.batch.file.name", "output.{id}.{run.time}.json")!; - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -400,7 +400,7 @@ private string GetOutputBatchFileName() var time = DateTime.Now.ToFileTime().ToString(); if (file.Contains("{time}")) file = file.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -408,12 +408,12 @@ private string GetOutputBatchFileName() private string GetOutputSrtFileName() { - var file = _values.GetOrDefault("output.srt.file.name", "output.{id}.{run.time}.srt"); + var file = _values.GetOrDefault("output.srt.file.name", "output.{id}.{run.time}.srt")!; - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -421,12 +421,12 @@ private string GetOutputSrtFileName() private string GetOutputVttFileName() { - var file = _values.GetOrDefault("output.vtt.file.name", "output.{id}.{run.time}.vtt"); + var file = _values.GetOrDefault("output.vtt.file.name", "output.{id}.{run.time}.vtt")!; - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -446,18 +446,19 @@ private void OutputBatchJsonFile() writer.Flush(); var text = Encoding.UTF8.GetString(stream.ToArray()) + Environment.NewLine; - FileHelpers.WriteAllText(_outputBatchFileName, text, Encoding.UTF8); + FileHelpers.WriteAllText(_outputBatchFileName!, text, Encoding.UTF8); } private void OutputSrtFile() - { + { var text = GetSrtFile() + Environment.NewLine; - FileHelpers.WriteAllText(_outputSrtFileName, text, Encoding.UTF8); + FileHelpers.WriteAllText(_outputSrtFileName!, text, Encoding.UTF8); - foreach (var language in _values.GetOrDefault("target.language.config", "")?.Split(';', StringSplitOptions.RemoveEmptyEntries)) + var languages = GetTargetLanguages(); + foreach (var language in languages) { var translated = GetSrtFile(language) + Environment.NewLine; - var translatedFile = FileHelpers.AppendToFileName(_outputSrtFileName, $".{language}", ""); + var translatedFile = FileHelpers.AppendToFileName(_outputSrtFileName!, $".{language}", ""); FileHelpers.WriteAllText(translatedFile, translated, Encoding.UTF8); } } @@ -465,21 +466,28 @@ private void OutputSrtFile() private void OutputVttFile() { var text = GetVttFile() + Environment.NewLine; - FileHelpers.WriteAllText(_outputVttFileName, text, Encoding.UTF8); + FileHelpers.WriteAllText(_outputVttFileName!, text, Encoding.UTF8); - foreach (var language in _values.GetOrDefault("target.language.config", "")?.Split(';', StringSplitOptions.RemoveEmptyEntries)) + var languages = GetTargetLanguages(); + foreach (var language in languages) { var translated = GetVttFile(language) + Environment.NewLine; - var translatedFile = FileHelpers.AppendToFileName(_outputVttFileName, $".{language}", ""); + var translatedFile = FileHelpers.AppendToFileName(_outputVttFileName!, $".{language}", ""); FileHelpers.WriteAllText(translatedFile, translated, Encoding.UTF8); } } + private string[] GetTargetLanguages() + { + var languages = _values.GetOrEmpty("target.language.config")?.Split(';', StringSplitOptions.RemoveEmptyEntries); + return languages ?? Array.Empty(); + } + private void WriteBatchAudioFileJsonObject(Utf8JsonWriter writer) { writer.WriteStartObject(); - var id = _propertyCache["audio.input.id"]; + var id = _propertyCache!["audio.input.id"]; var file = _propertyCache["audio.input.file"]; if (file != null && file.StartsWith("http")) @@ -489,7 +497,7 @@ private void WriteBatchAudioFileJsonObject(Utf8JsonWriter writer) } else { - var existing = FileHelpers.FindFileInDataPath(file, _values); + var existing = FileHelpers.FindFileInDataPath(file!, _values); writer.WriteString("AudioFileName", file ?? id); writer.WriteString("AudioFileUrl", existing ?? file ?? id); } @@ -502,10 +510,10 @@ private void WriteBatchAudioFileJsonObject(Utf8JsonWriter writer) writer.WriteEndObject(); } - private string GetSrtFile(string language = null) + private string GetSrtFile(string? language = null) { StringBuilder sb = new StringBuilder(); - foreach (var caption in CaptionHelper.GetCaptions(language, 37, 3, _outputResultCache)) + foreach (var caption in CaptionHelper.GetCaptions(language, 37, 3, _outputResultCache!)) { sb.AppendLine($"{caption.Sequence}"); sb.AppendLine($@"{caption.Begin:hh\:mm\:ss\,fff} --> {caption.End:hh\:mm\:ss\,fff}"); @@ -515,10 +523,10 @@ private string GetSrtFile(string language = null) return sb.ToString().Trim(); } - private string GetVttFile(string language = null) + private string GetVttFile(string? language = null) { StringBuilder sb = new StringBuilder($"WEBVTT{Environment.NewLine}"); - foreach (var caption in CaptionHelper.GetCaptions(language, 37, 3, _outputResultCache)) + foreach (var caption in CaptionHelper.GetCaptions(language, 37, 3, _outputResultCache!)) { sb.AppendLine(); sb.AppendLine($@"{caption.Begin:hh\:mm\:ss\.fff} --> {caption.End:hh\:mm\:ss\.fff}"); @@ -545,7 +553,7 @@ private void WriteBatchAudioFileCombinedResultsJsonProperty(Utf8JsonWriter write private string GetBatchCombinedText(string kind) { StringBuilder sb = new StringBuilder(); - foreach (var result in _outputResultCache) + foreach (var result in _outputResultCache!) { if (IsFinalResult(result)) { @@ -558,7 +566,7 @@ private string GetBatchCombinedText(string kind) private bool IsFinalResult(object result) { - RecognitionResult final = result as RecognitionResult; + var final = result as RecognitionResult; return final?.Reason == ResultReason.RecognizedSpeech || final?.Reason == ResultReason.RecognizedIntent || final?.Reason == ResultReason.TranslatedSpeech; @@ -597,7 +605,7 @@ private string GetResultText(object result, string kind) private void WriteBatchAudioFileSegmentResultsJsonProperty(Utf8JsonWriter writer, string arrayName) { writer.WriteStartArray(arrayName); - foreach (var result in _outputResultCache) + foreach (var result in _outputResultCache!) { WriteBatchAudioFileSegmentJsonObject(writer, result); } @@ -643,7 +651,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, SpeechR var json = result.Properties.GetProperty(PropertyId.SpeechServiceResponse_JsonResult); var parsed = !string.IsNullOrEmpty(json) ? JsonDocument.Parse(json) : null; - var status = parsed.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); + var status = parsed?.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); writer.WriteString("RecognitionStatus", status); writer.WriteString("ChannelNumber", "0"); @@ -654,7 +662,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, SpeechR writer.WriteNumber("DurationInSeconds", Math.Round(result.Duration.TotalSeconds, 2)); writer.WritePropertyName("NBest"); - writer.WriteRawValue(parsed.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); + writer.WriteRawValue(parsed?.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); writer.WriteEndObject(); return true; @@ -677,7 +685,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Transla var json = result.Properties.GetProperty(PropertyId.SpeechServiceResponse_JsonResult); var parsed = !string.IsNullOrEmpty(json) ? JsonDocument.Parse(json) : null; - var status = parsed.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); + var status = parsed?.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); writer.WriteString("RecognitionStatus", status); writer.WriteString("ChannelNumber", "0"); @@ -688,7 +696,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Transla writer.WriteNumber("DurationInSeconds", Math.Round(result.Duration.TotalSeconds, 2)); writer.WritePropertyName("NBest"); - writer.WriteRawValue(parsed.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); + writer.WriteRawValue(parsed?.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); writer.WriteEndObject(); return true; @@ -711,7 +719,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Convers var json = result.Properties.GetProperty(PropertyId.SpeechServiceResponse_JsonResult); var parsed = !string.IsNullOrEmpty(json) ? JsonDocument.Parse(json) : null; - var status = parsed.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); + var status = parsed?.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); writer.WriteString("RecognitionStatus", status); writer.WriteString("ChannelNumber", "0"); @@ -722,7 +730,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Convers writer.WriteNumber("DurationInSeconds", Math.Round(result.Duration.TotalSeconds, 2)); writer.WritePropertyName("NBest"); - writer.WriteRawValue(parsed.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); + writer.WriteRawValue(parsed?.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); writer.WriteEndObject(); return true; @@ -745,7 +753,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Meeting var json = result.Properties.GetProperty(PropertyId.SpeechServiceResponse_JsonResult); var parsed = !string.IsNullOrEmpty(json) ? JsonDocument.Parse(json) : null; - var status = parsed.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); + var status = parsed?.GetPropertyStringOrNull("RecognitionStatus") ?? result.Reason.ToString(); writer.WriteString("RecognitionStatus", status); writer.WriteString("ChannelNumber", "0"); @@ -756,7 +764,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Meeting writer.WriteNumber("DurationInSeconds", Math.Round(result.Duration.TotalSeconds, 2)); writer.WritePropertyName("NBest"); - writer.WriteRawValue(parsed.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); + writer.WriteRawValue(parsed?.GetPropertyElementOrNull("NBest")?.GetRawText() ?? "[]"); writer.WriteEndObject(); return true; @@ -765,7 +773,7 @@ private bool WriteBatchAudioFileSegmentJsonObject(Utf8JsonWriter writer, Meeting private double GetBatchAudioLengthInSeconds() { double length = 0; - foreach (var result in _outputResultCache) + foreach (var result in _outputResultCache!) { double offset, duration; GetResultOffsetAndDuration(result, out offset, out duration); @@ -860,10 +868,10 @@ public void EnsureCheckAll(string name, string value) private void AppendCheckAll(char ch, string name, string value) { EnsureInitCheckAllCache(name); - _checkAllCache[name].Add(value); + _checkAllCache![name].Add(value); } - private void EnsureInitCheckAllCache(string name = null) + private void EnsureInitCheckAllCache(string name) { if (_checkAllCache == null) { @@ -886,7 +894,7 @@ public void EnsureOutputAll(string name, string value) EnsureOutputAll('\n', name, "{0}", value); } - public string GetAllOutput(string name, string defaultValue = null) + public string? GetAllOutput(string name, string? defaultValue = null) { if (_outputAllCache == null || !_outputAllCache.ContainsKey(name)) return defaultValue; @@ -895,7 +903,7 @@ public string GetAllOutput(string name, string defaultValue = null) { if (sb.Length > 0) { - sb.Append(_outputAllSeparatorCache[name]); + sb.Append(_outputAllSeparatorCache![name]); } sb.Append(item); } @@ -912,11 +920,11 @@ private void EnsureOutputAll(char ch, string name, string format, params object[ private void AppendOutputAll(char ch, string name, string value) { EnsureInitOutputAllCache(name); - _outputAllCache[name].Add(value); - _outputAllSeparatorCache[name] = ch; + _outputAllCache![name].Add(value); + _outputAllSeparatorCache![name] = ch; } - private void EnsureInitOutputAllCache(string name = null) + private void EnsureInitOutputAllCache(string name) { if (_outputAllCache == null) { @@ -935,7 +943,7 @@ private void FlushOutputAllCache() if (!_outputAll) return; var overwrite = _values.GetOrDefault("output.overwrite", false); - if (overwrite) File.Delete(_outputAllFileName); + if (overwrite) File.Delete(_outputAllFileName!); switch (_outputAllFileType) { @@ -954,9 +962,9 @@ private void FlushOutputAllCache() private string GetOutputAllFileName() { - var file = _values.GetOrDefault("output.all.file.name", "output.{run.time}." + GetOutputAllFileType()); + var file = _values.GetOrDefault("output.all.file.name", "output.{run.time}." + GetOutputAllFileType())!; - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -965,7 +973,7 @@ private string GetOutputAllFileName() var time = DateTime.Now.ToFileTime().ToString(); if (file.Contains("{time}")) file = file.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -973,13 +981,13 @@ private string GetOutputAllFileName() private string GetOutputAllFileType() { - return _values.GetOrDefault("output.all.file.type", "tsv"); + return _values.GetOrDefault("output.all.file.type", "tsv")!; } private string[] GetOutputAllColumns() { bool hasColumns = _values.Contains("output.all.tsv.file.columns"); - if (hasColumns) return _values.Get("output.all.tsv.file.columns").Split(';', '\r', '\n', '\t'); + if (hasColumns) return _values.Get("output.all.tsv.file.columns")!.Split(';', '\r', '\n', '\t'); var output = _values.Names.Where(x => x.StartsWith("output.all.") && !x.Contains(".tsv.") && _values.GetOrDefault(x, false)); return output.Select(x => x.Remove(0, "output.all.".Length)).ToArray(); @@ -987,15 +995,15 @@ private string[] GetOutputAllColumns() private void OutputAllJsonFile() { - var json = JsonHelpers.GetJsonObjectText(_outputAllCache) + Environment.NewLine; - FileHelpers.AppendAllText(_outputAllFileName, json, Encoding.UTF8); + var json = JsonHelpers.GetJsonObjectText(_outputAllCache!) + Environment.NewLine; + FileHelpers.AppendAllText(_outputAllFileName!, json, Encoding.UTF8); } private void OutputAllTsvFile() { var columns = GetOutputAllColumns(); - EnsureOutputAllTsvFileHeader(_outputAllFileName, columns); - OutputAllTsvFileRow(_outputAllFileName, columns); + EnsureOutputAllTsvFileHeader(_outputAllFileName!, columns); + OutputAllTsvFileRow(_outputAllFileName!, columns); } private void EnsureOutputAllTsvFileHeader(string file, string[] columns) @@ -1018,7 +1026,7 @@ private void OutputAllTsvFileRow(string file, string[] columns) StringBuilder sb = new StringBuilder(); foreach (var column in columns) { - var value = GetAllOutput(column, ""); + var value = GetAllOutput(column, "")!; sb.Append(EncodeOutputValue(value)); sb.Append('\t'); } @@ -1068,7 +1076,7 @@ public void EnsureOutputEach(string name, string format, params object[] arg) private void AddOutputEachCache(string name, string value) { EnsureInitOutputEachCache(); - _outputEachCache[name] = value; + _outputEachCache![name] = value; } private void EnsureInitOutputEachCache() @@ -1099,7 +1107,7 @@ private void FlushOutputEachCacheStage2(bool overwrite = false) if (!_outputEach) return; overwrite = overwrite && _values.GetOrDefault("output.overwrite", false); - if (overwrite) File.Delete(_outputEachFileName); + if (overwrite) File.Delete(_outputEachFileName!); switch (_outputEachFileType) { @@ -1118,9 +1126,9 @@ private void FlushOutputEachCacheStage2(bool overwrite = false) private string GetOutputEachFileName() { - var file = _values.GetOrDefault("output.each.file.name", "each.{run.time}." + GetOutputEachFileType()); + var file = _values.GetOrDefault("output.each.file.name", "each.{run.time}." + GetOutputEachFileType())!; - var id = _values.GetOrDefault("audio.input.id", ""); + var id = _values.GetOrEmpty("audio.input.id"); if (file.Contains("{id}")) file = file.Replace("{id}", id); var pid = Process.GetCurrentProcess().Id.ToString(); @@ -1129,7 +1137,7 @@ private string GetOutputEachFileName() var time = DateTime.Now.ToFileTime().ToString(); if (file.Contains("{time}")) file = file.Replace("{time}", time); - var runTime = _values.GetOrDefault("x.run.time", ""); + var runTime = _values.GetOrEmpty("x.run.time"); if (file.Contains("{run.time}")) file = file.Replace("{run.time}", runTime); return file.ReplaceValues(_values); @@ -1137,13 +1145,13 @@ private string GetOutputEachFileName() private string GetOutputEachFileType() { - return _values.GetOrDefault("output.each.file.type", "tsv"); + return _values.GetOrDefault("output.each.file.type", "tsv")!; } private string[] GetOutputEachColumns() { bool hasColumns = _values.Contains("output.each.tsv.file.columns"); - if (hasColumns) return _values.Get("output.each.tsv.file.columns").Split(';', '\r', '\n', '\t'); + if (hasColumns) return _values.Get("output.each.tsv.file.columns")!.Split(';', '\r', '\n', '\t'); var output = _values.Names.Where(x => x.StartsWith("output.each.") && !x.Contains(".tsv.") && _values.GetOrDefault(x, false)); return output.Select(x => x.Remove(0, "output.each.".Length)).ToArray(); @@ -1151,15 +1159,15 @@ private string[] GetOutputEachColumns() private void OutputEachJsonFile() { - var json = JsonHelpers.GetJsonArrayText(_outputEachCache2) + Environment.NewLine; - FileHelpers.AppendAllText(_outputEachFileName, json, Encoding.UTF8); + var json = JsonHelpers.GetJsonArrayText(_outputEachCache2!) + Environment.NewLine; + FileHelpers.AppendAllText(_outputEachFileName!, json, Encoding.UTF8); } private void OutputEachTsvFile() { var columns = GetOutputEachColumns(); - EnsureOutputEachTsvFileHeader(_outputEachFileName, columns); - OutputEachTsvFileRow(_outputEachFileName, columns); + EnsureOutputEachTsvFileHeader(_outputEachFileName!, columns); + OutputEachTsvFileRow(_outputEachFileName!, columns); } private void EnsureOutputEachTsvFileHeader(string file, string[] columns) @@ -1864,7 +1872,7 @@ private void EnsureOutputIntentResultEntities(string namePrefix, string entityJs { var value = parsed.GetPropertyStringOrNull(x); var valueOk = value != null; - if (valueOk) EnsureOutputEach($"{namePrefix}.{x}.entity", value); + if (valueOk) EnsureOutputEach($"{namePrefix}.{x}.entity", value!); } } } @@ -2590,7 +2598,7 @@ private void CheckAll() var jmesValue = _values.GetOrDefault("check.jmes", null); if (jmesValue != null) { - var json = JsonHelpers.GetJsonObjectText(_checkAllCache); + var json = JsonHelpers.GetJsonObjectText(_checkAllCache!); if(String.IsNullOrEmpty(json)) { SetPassed(false); @@ -2632,7 +2640,7 @@ private void CheckResult() bool checkEval = false; // Match our detailed result. - foreach (RecognitionResult result in _outputResultCache) + foreach (RecognitionResult result in _outputResultCache!) { // TODO: add other result types if (result.Reason == ResultReason.RecognizedSpeech || result.Reason == ResultReason.TranslatedSpeech || @@ -2715,7 +2723,7 @@ private void CheckTranscriptWer(string check) if (transcript == null) return; var textName = "recognizer.recognized.result." + check; - var text = GetAllOutput(textName); + var text = GetAllOutput(textName)!; if (text == null) return; var checkName = "check.sr.transcript." + check + ".wer"; @@ -2726,8 +2734,8 @@ private void CheckTranscriptWer(string check) var werUrl = _values["wer.sr.url"]; var isUrlOk = !string.IsNullOrEmpty(werUrl) && werUrl.StartsWith("http"); var wer = isUrlOk ? - GetWerFromUrl(werUrl, transcript, text, _targetCulture.Name) : - WerHelpers.CalculateWer(transcript, text, _targetCulture, ignorePunctuation); + GetWerFromUrl(werUrl!, transcript, text, _targetCulture!.Name) : + WerHelpers.CalculateWer(transcript, text, _targetCulture!, ignorePunctuation); var pass = CheckNumber(wer.ErrorRate, checkName, checking); if (!pass) SetPassed(false); @@ -2801,7 +2809,7 @@ private void CheckTranscriptText() private void CheckTranscriptText(string check) { var textName = "recognizer.recognized.result." + check; - var text = GetAllOutput(textName); + var text = GetAllOutput(textName)!; var checkName = "check.sr.transcript." + check; @@ -2816,7 +2824,7 @@ private void CheckTranscriptText(string check) private void CheckTranscriptTextExpr(string textName, string text, string check) { var checkName = "check.sr.transcript." + check; - var checking = _values[checkName]; + var checking = _values[checkName] ?? string.Empty; if (checking.StartsWith("eq=")) { @@ -2859,14 +2867,14 @@ private void CheckTranscriptTextIn(string textName, string text, string check) var checkName = "check.sr.transcript." + check + ".in"; var checking = _values[checkName]; - var checkItems = checking.Split(';', '\r', '\n'); - var pass = checkItems.Count(x => x.CompareTo(text) == 0) > 0; + var checkItems = checking?.Split(';', '\r', '\n'); + var pass = checkItems?.Count(x => x.CompareTo(text) == 0) > 0; if (!pass) SetPassed(false); _values.Add("output.all." + checkName, "true"); EnsureCacheAll(checkName, pass ? "true" : "false"); - DebugWriteCheckTranscriptText(textName, text, checkName, checking, pass); + DebugWriteCheckTranscriptText(textName, text, checkName, checking!, pass); } private void CheckTranscriptTextContains(string textName, string text, string check) @@ -2874,14 +2882,14 @@ private void CheckTranscriptTextContains(string textName, string text, string ch var checkName = "check.sr.transcript." + check + ".contains"; var checking = _values[checkName]; - var checkItems = checking.Split(';', '\r', '\n'); - var pass = checkItems.Count(x => text.Contains(x)) == checkItems.Count(); + var checkItems = checking?.Split(';', '\r', '\n'); + var pass = checkItems?.Count(x => text.Contains(x)) == checkItems?.Count(); if (!pass) SetPassed(false); _values.Add("output.all." + checkName, "true"); EnsureCacheAll(checkName, pass ? "true" : "false"); - DebugWriteCheckTranscriptText(textName, text, checkName, checking, pass); + DebugWriteCheckTranscriptText(textName, text, checkName, checking!, pass); } private void CheckTranscriptTextNotIn(string textName, string text, string check) @@ -2889,13 +2897,13 @@ private void CheckTranscriptTextNotIn(string textName, string text, string check var checkName = "check.sr.transcript." + check + ".not.in"; var checking = _values[checkName]; - var pass = checking.Split(';', '\r', '\n').Count(x => x.CompareTo(text) == 0) == 0; + var pass = checking?.Split(';', '\r', '\n')?.Count(x => x.CompareTo(text) == 0) == 0; if (!pass) SetPassed(false); _values.Add("output.all." + checkName, "true"); EnsureCacheAll(checkName, pass ? "true" : "false"); - DebugWriteCheckTranscriptText(textName, text, checkName, checking, pass); + DebugWriteCheckTranscriptText(textName, text, checkName, checking!, pass); } private void CheckTranscriptTextNotContains(string textName, string text, string check) @@ -2903,13 +2911,13 @@ private void CheckTranscriptTextNotContains(string textName, string text, string var checkName = "check.sr.transcript." + check + ".not.contains"; var checking = _values[checkName]; - var pass = checking.Split(';', '\r', '\n').Count(x => text.Contains(x)) == 0; + var pass = checking?.Split(';', '\r', '\n')?.Count(x => text.Contains(x)) == 0; if (!pass) SetPassed(false); _values.Add("output.all." + checkName, "true"); EnsureCacheAll(checkName, pass ? "true" : "false"); - DebugWriteCheckTranscriptText(textName, text, checkName, checking, pass); + DebugWriteCheckTranscriptText(textName, text, checkName, checking!, pass); } private void DebugWriteCheckTranscriptWer(string transcriptName, string transcript, string textName, string text, string checkName, string checking, bool pass) @@ -2936,7 +2944,7 @@ private void FlushOutputZipFile() { if (!_outputAll && !_outputEach && !_outputBatch) return; - var zipFileName = _values.GetOrDefault("output.zip.file", ""); + var zipFileName = _values.GetOrEmpty("output.zip.file"); if (string.IsNullOrEmpty(zipFileName)) return; TryCatchHelpers.TryCatchRetry(() => @@ -2949,11 +2957,11 @@ private void FlushOutputZipFile() using (var archive = ZipFile.Open(zipFileName, ZipArchiveMode.Update)) { - if (_outputAll) AddToZip(archive, _outputAllFileName); - if (_outputEach) AddToZip(archive, _outputEachFileName); - if (_outputBatch) AddToZip(archive, _outputBatchFileName); - if (_outputVtt) AddToZip(archive, _outputVttFileName); - if (_outputSrt) AddToZip(archive, _outputSrtFileName); + if (_outputAll) AddToZip(archive, _outputAllFileName!); + if (_outputEach) AddToZip(archive, _outputEachFileName!); + if (_outputBatch) AddToZip(archive, _outputBatchFileName!); + if (_outputVtt) AddToZip(archive, _outputVttFileName!); + if (_outputSrt) AddToZip(archive, _outputSrtFileName!); } }); } @@ -2981,37 +2989,37 @@ private void AddToZip(ZipArchive zip, string file) private bool _debugOutput = false; private bool _outputBatch = false; - private string _outputBatchFileName = null; + private string? _outputBatchFileName = null; private bool _outputVtt = false; - private string _outputVttFileName = null; + private string? _outputVttFileName = null; private bool _outputSrt = false; - private string _outputSrtFileName = null; + private string? _outputSrtFileName = null; private bool _cacheResults = false; - private List _outputResultCache = null; - private Dictionary _propertyCache = null; - private Dictionary _propertyCollectionCache = null; + private List? _outputResultCache = null; + private Dictionary? _propertyCache = null; + private Dictionary? _propertyCollectionCache = null; private bool _outputAll = false; - private string _outputAllFileName = null; - private string _outputAllFileType = null; - private Dictionary> _outputAllCache; - private Dictionary _outputAllSeparatorCache; + private string? _outputAllFileName = null; + private string? _outputAllFileType = null; + private Dictionary>? _outputAllCache; + private Dictionary? _outputAllSeparatorCache; private bool _outputEach = false; private bool _overwriteEach = false; - private string _outputEachFileName = null; - private string _outputEachFileType = null; - private Dictionary _outputEachCache; - private List> _outputEachCache2; + private string? _outputEachFileName = null; + private string? _outputEachFileType = null; + private Dictionary? _outputEachCache; + private List>? _outputEachCache2; - private Dictionary> _checkAllCache; + private Dictionary>? _checkAllCache; - private CultureInfo _sourceCulture; - private CultureInfo _targetCulture; + private CultureInfo? _sourceCulture; + private CultureInfo? _targetCulture; } } diff --git a/src/extensions/template_extension/TemplateFactory.cs b/src/extensions/template_extension/TemplateFactory.cs index 4ae9d0b9..3179e67b 100644 --- a/src/extensions/template_extension/TemplateFactory.cs +++ b/src/extensions/template_extension/TemplateFactory.cs @@ -267,7 +267,7 @@ private static Dictionary UpdateParameters(List files, D return parameters; } - private static void UpdateParameters(string? jsonFile, Dictionary parameters) + private static void UpdateParameters(string jsonFile, Dictionary parameters) { var json = FileHelpers.ReadAllText(jsonFile, new UTF8Encoding(false)); foreach (var item in JsonDocument.Parse(json).RootElement.EnumerateObject()) @@ -304,7 +304,7 @@ private static IEnumerable ProcessTemplates(string templateName, Templat { if (!file.StartsWith(root)) throw new Exception("Invalid file name"); var outputFile = file.Substring(root.Length + templateName.Length + 1); - var outputFileWithPath = PathHelpers.Combine(outputDirectory, outputFile); + var outputFileWithPath = PathHelpers.Combine(outputDirectory, outputFile)!; var isBinary = file.EndsWith(".png") || file.EndsWith(".ico"); if (!isBinary) diff --git a/src/extensions/testframework/JunitXmlTestReporter.cs b/src/extensions/testframework/JunitXmlTestReporter.cs index a92ce91e..3d463a66 100644 --- a/src/extensions/testframework/JunitXmlTestReporter.cs +++ b/src/extensions/testframework/JunitXmlTestReporter.cs @@ -12,8 +12,10 @@ namespace Azure.AI.Details.Common.CLI.TestFramework { public static class JunitXmlTestReporter { - public static string WriteResultsFile(TestRun testRun, string resultsFile = "test-results.xml") + public static string WriteResultsFile(TestRun testRun, string? resultsFile = null) { + resultsFile ??= "test-results.xml"; + var testCases = testRun.TestCases; var testResults = testRun.TestResults; var startTime = testRun.StartTime; @@ -50,17 +52,23 @@ public static string WriteResultsFile(TestRun testRun, string resultsFile = "tes var debugTrace = testResult.Messages.FirstOrDefault(x => x.Category == TestResultMessage.DebugTraceCategory)?.Text; var message = testResult.Messages.FirstOrDefault(x => x.Category == TestResultMessage.AdditionalInfoCategory)?.Text; - writer.WriteStartElement("system-out"); - writer.WriteRaw(System.Security.SecurityElement - .Escape(stdout.Replace("\u001b", string.Empty)) - .Replace("\r\n", " \n")); - writer.WriteEndElement(); + if (stdout != null) + { + writer.WriteStartElement("system-out"); + writer.WriteRaw(System.Security.SecurityElement + .Escape(stdout.Replace("\u001b", string.Empty)) + .Replace("\r\n", " \n")); + writer.WriteEndElement(); + } - writer.WriteStartElement("system-err"); - writer.WriteRaw(System.Security.SecurityElement - .Escape(stderr.Replace("\u001b", string.Empty)) - .Replace("\r\n", " \n")); - writer.WriteEndElement(); + if (stderr != null) + { + writer.WriteStartElement("system-err"); + writer.WriteRaw(System.Security.SecurityElement + .Escape(stderr.Replace("\u001b", string.Empty)) + .Replace("\r\n", " \n")); + writer.WriteEndElement(); + } if (testResult.Outcome == TestOutcome.Failed) { diff --git a/src/extensions/testframework/Logger.cs b/src/extensions/testframework/Logger.cs index a6cf0c63..bf83f495 100644 --- a/src/extensions/testframework/Logger.cs +++ b/src/extensions/testframework/Logger.cs @@ -73,7 +73,7 @@ public static void LogError(string text) #region private methods and data - private static IYamlTestFrameworkLogger logger = null; + private static IYamlTestFrameworkLogger? logger = null; #endregion } diff --git a/src/extensions/testframework/TrxXmlTestReporter.cs b/src/extensions/testframework/TrxXmlTestReporter.cs index 117a0edc..db1cb7dc 100644 --- a/src/extensions/testframework/TrxXmlTestReporter.cs +++ b/src/extensions/testframework/TrxXmlTestReporter.cs @@ -12,8 +12,10 @@ namespace Azure.AI.Details.Common.CLI.TestFramework { public static class TrxXmlTestReporter { - public static string WriteResultsFile(TestRun testRun, string resultsFile = "test-results.trx") + public static string WriteResultsFile(TestRun testRun, string? resultsFile = null) { + resultsFile ??= "test-results.trx"; + var testCases = testRun.TestCases; var testResults = testRun.TestResults; var startTime = testRun.StartTime; diff --git a/src/extensions/testframework/YamlEnvHelpers.cs b/src/extensions/testframework/YamlEnvHelpers.cs index da23dad3..8cb47c81 100644 --- a/src/extensions/testframework/YamlEnvHelpers.cs +++ b/src/extensions/testframework/YamlEnvHelpers.cs @@ -66,7 +66,7 @@ public static Dictionary GetEnvironmentFromMultiLineString(strin public static Dictionary GetCurrentProcessEnvironment() { var env = Environment.GetEnvironmentVariables(); - return env.Keys.Cast().ToDictionary(key => key, key => env[key].ToString()); + return env.Keys.Cast().ToDictionary(key => key, key => env[key]?.ToString() ?? string.Empty); } public static Dictionary UpdateCopyEnvironment(Dictionary environment, YamlMappingNode mapping) diff --git a/src/extensions/testframework/YamlHelpers.cs b/src/extensions/testframework/YamlHelpers.cs index 3db79e3b..65544038 100644 --- a/src/extensions/testframework/YamlHelpers.cs +++ b/src/extensions/testframework/YamlHelpers.cs @@ -53,7 +53,7 @@ public static string ToYamlOrJsonString(YamlNode node, bool yaml) using var reader = new StringReader(writer.ToString()); var deserializer = new Deserializer(); - var yamlObject = deserializer.Deserialize(reader); + var yamlObject = deserializer.Deserialize(reader)!; var trimmed = serializer.Serialize(yamlObject).Trim('\r', '\n'); return yaml ? trimmed : trimmed.Replace("\t", "\\t").Replace("\f", "\\f"); diff --git a/src/extensions/testframework/YamlNodeExtensions.cs b/src/extensions/testframework/YamlNodeExtensions.cs index c8320cc1..99c774ac 100644 --- a/src/extensions/testframework/YamlNodeExtensions.cs +++ b/src/extensions/testframework/YamlNodeExtensions.cs @@ -37,17 +37,17 @@ public static YamlScalarNode ConvertScalarSequenceToMultiLineTsvScalarNode(this return new YamlScalarNode(text); } - public static string ConvertScalarSequenceToMultilineTsvString(this YamlNode node, string[] keys = null) + public static string? ConvertScalarSequenceToMultilineTsvString(this YamlNode node, string[] keys) { // ensure it's a sequence var ok = node is YamlSequenceNode; if (!ok) return null; var lines = new List(); - foreach (var item in (node as YamlSequenceNode).Children) + foreach (var item in (node as YamlSequenceNode)!.Children) { var line = item is YamlScalarNode - ? (item as YamlScalarNode).Value + ? (item as YamlScalarNode)?.Value : item is YamlSequenceNode ? item.ConvertScalarSequenceToTsvString(keys) : item.ConvertScalarMapToTsvString(keys); @@ -57,12 +57,12 @@ public static string ConvertScalarSequenceToMultilineTsvString(this YamlNode nod Logger.LogIf(invalidItem, $"Invalid item at ({item.Start.Line},{item.Start.Column})"); if (invalidItem) return null; - lines.Add(line); + lines.Add(line!); } return string.Join("\n", lines); } - public static string ConvertScalarSequenceToTsvString(this YamlNode node, string[] keys = null) + public static string? ConvertScalarSequenceToTsvString(this YamlNode node, string[]? keys = null) { // ensure it's a sequence (list/array) var sequence = node as YamlSequenceNode; @@ -75,7 +75,7 @@ public static string ConvertScalarSequenceToTsvString(this YamlNode node, string // join the scalar children separated by tabs var tsv = string.Join("\t", sequence.Children - .Select(x => (x as YamlScalarNode).Value)); + .Select(x => (x as YamlScalarNode)?.Value)); // if we don't have enough items, append empty string columns (count of items == count of tabs + 1) while (tsv.Count(x => x == '\t') + 1 < keys?.Length) @@ -88,7 +88,7 @@ public static string ConvertScalarSequenceToTsvString(this YamlNode node, string return tsv; } - public static string ConvertScalarMapToTsvString(this YamlNode node, string[] keys) + public static string? ConvertScalarMapToTsvString(this YamlNode node, string[] keys) { // ensure it's a mapping node and we have keys var mapping = node as YamlMappingNode; @@ -100,14 +100,14 @@ public static string ConvertScalarMapToTsvString(this YamlNode node, string[] ke if (count > 0) return null; // ensure the key specified is in the list of keys - count = mapping.Count(x => !keys.Contains((x.Key as YamlScalarNode).Value)); + count = mapping.Count(x => !keys.Contains((x.Key as YamlScalarNode)?.Value)); Logger.LogIf(count > 0, $"Invalid: key not found count({count}) > 0"); if (count > 0) return null; // join the scalar children ordered by keys, separated by tabs var tsv = string.Join("\t", keys .Select(key => mapping.Children.ContainsKey(key) - ? (mapping.Children[key] as YamlScalarNode).Value + ? (mapping.Children[key] as YamlScalarNode)?.Value : "")); tsv = tsv.Replace('\n', '\f'); diff --git a/src/extensions/testframework/YamlTagHelpers.cs b/src/extensions/testframework/YamlTagHelpers.cs index 305788d2..5c41d039 100644 --- a/src/extensions/testframework/YamlTagHelpers.cs +++ b/src/extensions/testframework/YamlTagHelpers.cs @@ -13,7 +13,7 @@ namespace Azure.AI.Details.Common.CLI.TestFramework { public class YamlTagHelpers { - public static FileInfo FindDefaultTagsFile(DirectoryInfo directory) + public static FileInfo? FindDefaultTagsFile(DirectoryInfo directory) { var found = directory.GetFiles(YamlTestFramework.YamlDefaultTagsFileName); return found.Length == 1 @@ -58,7 +58,7 @@ public static Dictionary> UpdateCopyTags(Dictionary> UpdateCopyTags(Dictionary> tags, YamlNode tagNode, YamlNode tagsNode) + private static Dictionary> UpdateCopyTags(Dictionary> tags, YamlNode? tagNode, YamlNode? tagsNode) { // make a copy that we'll update and return tags = new Dictionary>(tags); @@ -75,7 +75,7 @@ private static Dictionary> UpdateCopyTags(Dictionary> tags, string name, string value) + private static void AddOptionalTag(Dictionary> tags, string name, string? value) { if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value)) { @@ -87,7 +87,7 @@ private static void AddOptionalTag(Dictionary> tags, string } } - private static void AddOptionalCommaSeparatedTags(Dictionary> tags, string values) + private static void AddOptionalCommaSeparatedTags(Dictionary> tags, string? values) { if (values != null) { @@ -98,7 +98,7 @@ private static void AddOptionalCommaSeparatedTags(Dictionary> tags, YamlMappingNode mapping, string keyPrefix = "") + private static void AddOptionalNameValueTags(Dictionary> tags, YamlMappingNode? mapping, string keyPrefix = "") { var children = mapping?.Children; if (children == null) return; @@ -107,9 +107,9 @@ private static void AddOptionalNameValueTags(Dictionary> ta { var key = keyPrefix + (child.Key as YamlScalarNode)?.Value; - if (child.Value is YamlScalarNode) + if (child.Value is YamlScalarNode asScalar) { - var value = (child.Value as YamlScalarNode)?.Value; + var value = asScalar.Value; AddOptionalTag(tags, key, value); } else if (child.Value is YamlSequenceNode || child.Value is YamlMappingNode) @@ -117,29 +117,29 @@ private static void AddOptionalNameValueTags(Dictionary> ta var value = child.Value.ToJsonString(); AddOptionalTag(tags, key, value); } - else if(child.Value is YamlMappingNode) + else if(child.Value is YamlMappingNode asMapping) { - AddOptionalNameValueTags(tags, child.Value as YamlMappingNode, $"{key}."); + AddOptionalNameValueTags(tags, asMapping, $"{key}."); } } } - private static void AddOptionalTagsForEachChild(Dictionary> tags, YamlSequenceNode sequence) + private static void AddOptionalTagsForEachChild(Dictionary> tags, YamlSequenceNode? sequence) { var children = sequence?.Children; if (children == null) return; foreach (var child in children) { - if (child is YamlScalarNode) + if (child is YamlScalarNode asScalar) { - AddOptionalTag(tags, "tag", (child as YamlScalarNode).Value); + AddOptionalTag(tags, "tag", asScalar.Value); continue; } - if (child is YamlMappingNode) + if (child is YamlMappingNode asMapping) { - AddOptionalNameValueTags(tags, child as YamlMappingNode); + AddOptionalNameValueTags(tags, asMapping); continue; } } diff --git a/src/extensions/testframework/YamlTestCaseFilter.cs b/src/extensions/testframework/YamlTestCaseFilter.cs index cf2299d2..be8844bb 100644 --- a/src/extensions/testframework/YamlTestCaseFilter.cs +++ b/src/extensions/testframework/YamlTestCaseFilter.cs @@ -105,7 +105,7 @@ private static HashSet GetSupportedFilterableNames(IEnumerable return filterable; } - private static object GetPropertyValue(TestCase test, string name) + private static object? GetPropertyValue(TestCase test, string name) { switch (name.ToLower()) { @@ -147,7 +147,7 @@ private static bool TestContainsText(TestCase test, string text) return test.DisplayName.Contains(text) || test.FullyQualifiedName.Contains(text) || test.Traits.Any(x => x.Name == text || x.Value.Contains(text)) - || supportedFilterProperties.Any(property => GetPropertyValue(test, property)?.ToString().Contains(text) == true); + || supportedFilterProperties.Any(property => GetPropertyValue(test, property)?.ToString()?.Contains(text) == true); } diff --git a/src/extensions/testframework/YamlTestCaseParser.cs b/src/extensions/testframework/YamlTestCaseParser.cs index a4a15f3c..e1efb84a 100644 --- a/src/extensions/testframework/YamlTestCaseParser.cs +++ b/src/extensions/testframework/YamlTestCaseParser.cs @@ -18,16 +18,16 @@ public partial class YamlTestCaseParser { public static IEnumerable TestCasesFromYaml(string source, FileInfo file) { - var defaultTags = YamlTagHelpers.FindAndGetDefaultTags(file.Directory); + var defaultTags = YamlTagHelpers.FindAndGetDefaultTags(file.Directory!); var workingDirectory = GetScalarString(null, defaultTags, "workingDirectory"); - workingDirectory = UpdateWorkingDirectory(file.Directory.FullName, workingDirectory); + workingDirectory = UpdateWorkingDirectory(file.Directory!.FullName, workingDirectory); var context = new YamlTestCaseParseContext() { Source = source, File = file, Area = GetRootArea(file), - Class = GetScalarString(null, defaultTags, "class", defaultClassName), + Class = GetScalarString(null, defaultTags, "class", defaultClassName)!, Tags = defaultTags, Environment = YamlEnvHelpers.GetDefaultEnvironment(true, workingDirectory), WorkingDirectory = workingDirectory @@ -42,7 +42,11 @@ public static IEnumerable TestCasesFromYaml(string source, FileInfo fi private static IEnumerable TestCasesFromYamlStream(YamlTestCaseParseContext context, YamlStream parsed) { var tests = new List(); - foreach (var document in parsed?.Documents) + + var docs = parsed?.Documents; + if (docs == null) return tests; + + foreach (var document in docs) { var fromDocument = TestCasesFromYamlDocumentRootNode(context, document.RootNode); if (fromDocument != null) @@ -53,14 +57,14 @@ private static IEnumerable TestCasesFromYamlStream(YamlTestCaseParseCo return tests; } - private static IEnumerable TestCasesFromYamlDocumentRootNode(YamlTestCaseParseContext context, YamlNode node) + private static IEnumerable? TestCasesFromYamlDocumentRootNode(YamlTestCaseParseContext context, YamlNode node) { return node is YamlMappingNode - ? TestCasesFromYamlMapping(context, node as YamlMappingNode) + ? TestCasesFromYamlMapping(context, (node as YamlMappingNode)!) : TestCasesFromYamlSequence(context, node as YamlSequenceNode); } - private static IEnumerable TestCasesFromYamlMapping(YamlTestCaseParseContext context, YamlMappingNode mapping) + private static IEnumerable? TestCasesFromYamlMapping(YamlTestCaseParseContext context, YamlMappingNode mapping) { var children = CheckForChildren(context, mapping); if (children != null) @@ -77,7 +81,7 @@ private static IEnumerable TestCasesFromYamlMapping(YamlTestCaseParseC return null; } - private static IEnumerable TestCasesFromYamlSequence(YamlTestCaseParseContext context, YamlSequenceNode sequence) + private static IEnumerable? TestCasesFromYamlSequence(YamlTestCaseParseContext context, YamlSequenceNode? sequence) { var tests = new List(); if (sequence == null) return tests; @@ -102,19 +106,21 @@ private static IEnumerable TestCasesFromYamlSequence(YamlTestCaseParse return tests; } - private static TestCase GetTestFromNode(YamlTestCaseParseContext context, YamlMappingNode mapping, int stepNumber = 0) + private static TestCase? GetTestFromNode(YamlTestCaseParseContext context, YamlMappingNode? mapping, int stepNumber = 0) { - string cli = GetScalarString(mapping, context.Tags, "cli"); - string parallelize = GetScalarString(mapping, context.Tags, "parallelize"); - string skipOnFailure = GetScalarString(mapping, context.Tags, "skipOnFailure"); - string workingDirectory = UpdateWorkingDirectory(mapping, context.WorkingDirectory); + if (mapping == null) return null; + + var cli = GetScalarString(mapping, context.Tags, "cli"); + var parallelize = GetScalarString(mapping, context.Tags, "parallelize"); + var skipOnFailure = GetScalarString(mapping, context.Tags, "skipOnFailure"); + string workingDirectory = UpdateWorkingDirectory(mapping!, context.WorkingDirectory); - string simulate = GetScalarString(mapping, "simulate"); - string command = GetScalarString(mapping, "command"); - string script = GetScalarString(mapping, "script"); - string bash = GetScalarString(mapping, "bash"); + var simulate = GetScalarString(mapping, "simulate"); + var command = GetScalarString(mapping, "command"); + var script = GetScalarString(mapping, "script"); + var bash = GetScalarString(mapping, "bash"); - string fullyQualifiedName = command == null && script == null && bash == null + var fullyQualifiedName = command == null && script == null && bash == null ? GetFullyQualifiedNameAndCommandFromShortForm(mapping, context.Area, context.Class, ref command, stepNumber) : GetFullyQualifiedName(mapping, context.Area, context.Class, stepNumber); fullyQualifiedName ??= GetFullyQualifiedName(context.Area, context.Class, $"Expected YAML node ('name') at {context.File.FullName}({mapping.Start.Line})", 0); @@ -167,11 +173,11 @@ private static TestCase GetTestFromNode(YamlTestCaseParseContext context, YamlMa return test; } - private static IEnumerable CheckForChildren(YamlTestCaseParseContext context, YamlMappingNode mapping) + private static IEnumerable? CheckForChildren(YamlTestCaseParseContext context, YamlMappingNode mapping) { if (mapping.Children.ContainsKey("steps") && mapping.Children["steps"] is YamlSequenceNode stepsSequence) { - context.Class = GetScalarString(mapping, "class", context.Class); + context.Class = GetScalarString(mapping, "class", context.Class)!; context.Area = UpdateArea(mapping, context.Area); context.Tags = YamlTagHelpers.UpdateCopyTags(context.Tags, mapping); context.Environment = YamlEnvHelpers.UpdateCopyEnvironment(context.Environment, mapping); @@ -182,13 +188,13 @@ private static IEnumerable CheckForChildren(YamlTestCaseParseContext c if (mapping.Children.ContainsKey("tests") && mapping.Children["tests"] is YamlSequenceNode testsSequence) { - context.Class = GetScalarString(mapping, "class", context.Class); + context.Class = GetScalarString(mapping, "class", context.Class)!; context.Area = UpdateArea(mapping, context.Area); context.Tags = YamlTagHelpers.UpdateCopyTags(context.Tags, mapping); context.Environment = YamlEnvHelpers.UpdateCopyEnvironment(context.Environment, mapping); context.WorkingDirectory = UpdateWorkingDirectory(mapping, context.WorkingDirectory); - return TestCasesFromYamlSequence(context, testsSequence).ToList(); + return TestCasesFromYamlSequence(context, testsSequence)?.ToList(); } return null; @@ -225,6 +231,7 @@ private static void CheckInvalidTestCaseNodes(YamlTestCaseParseContext context, { foreach (YamlScalarNode key in mapping.Children.Keys) { + if (key.Value == null) continue; if (!IsValidTestCaseNode(key.Value) && !test.DisplayName.EndsWith(key.Value)) { var error = $"Error parsing YAML: Unexpected YAML key/value ('{key.Value}', '{test.DisplayName}') in {context.File.FullName}({mapping[key].Start.Line})"; @@ -234,18 +241,18 @@ private static void CheckInvalidTestCaseNodes(YamlTestCaseParseContext context, } } - private static bool IsValidTestCaseNode(string value) + private static bool IsValidTestCaseNode(string? value) { - return ";area;class;name;cli;command;script;bash;timeout;foreach;arguments;input;expect;expect-gpt;not-expect;parallelize;simulate;skipOnFailure;tag;tags;workingDirectory;env;sanitize;".IndexOf($";{value};") >= 0; + return !string.IsNullOrEmpty(value) && ";area;class;name;cli;command;script;bash;timeout;foreach;arguments;input;expect;expect-gpt;not-expect;parallelize;simulate;skipOnFailure;tag;tags;workingDirectory;env;sanitize;".IndexOf($";{value};") >= 0; } private static void SetTestCaseProperty(TestCase test, string propertyName, YamlMappingNode mapping, string mappingName) { - string value = GetScalarString(mapping, mappingName); + var value = GetScalarString(mapping, mappingName); SetTestCaseProperty(test, propertyName, value); } - private static void SetTestCaseProperty(TestCase test, string propertyName, string value) + private static void SetTestCaseProperty(TestCase test, string propertyName, string? value) { if (value != null) { @@ -272,34 +279,35 @@ private static void SetTestCasePropertyMap(TestCase test, string propertyName, Y var argumentsNode = testNode.Children[mappingName]; if (argumentsNode == null) return; - if (argumentsNode is YamlScalarNode) + if (argumentsNode is YamlScalarNode asScalar) { - var value = (argumentsNode as YamlScalarNode).Value; + var value = asScalar.Value; SetTestCaseProperty(test, propertyName, $"\"{value}\""); } - else if (argumentsNode is YamlMappingNode) + else if (argumentsNode is YamlMappingNode asMapping) { - var asMapping = argumentsNode as YamlMappingNode; SetTestCasePropertyMap(test, propertyName, asMapping .Select(x => NormalizeToScalarKeyValuePair(test, x, workingDirectory))); } - else if (argumentsNode is YamlSequenceNode) + else if (argumentsNode is YamlSequenceNode asSequence) { - var asSequence = argumentsNode as YamlSequenceNode; - SetTestCasePropertyMap(test, propertyName, asSequence .Select(mapping => (mapping as YamlMappingNode)? .Select(x => NormalizeToScalarKeyValuePair(test, x, workingDirectory)))); } } - private static void SetTestCasePropertyMap(TestCase test, string propertyName, IEnumerable>> kvss) + private static void SetTestCasePropertyMap(TestCase test, string propertyName, IEnumerable>?> kvss) { // flatten the kvs - var kvs = kvss.SelectMany(x => x); + var kvs = kvss.Where(x => x != null).SelectMany(x => x!); // ensure all keys are unique, if not, transform appropriately - var keys = kvs.GroupBy(kv => (kv.Key as YamlScalarNode)?.Value).Select(g => g.Key).ToArray(); + var keys = kvs + .GroupBy(kv => (kv.Key as YamlScalarNode)?.Value) + .Where(g => g?.Key != null) + .Select(g => g.Key!) + .ToArray(); if (keys.Length < kvs.Count()) { Logger.Log($"keys.Length={keys.Length}, kvs.Count={kvs.Count()}"); @@ -308,8 +316,9 @@ private static void SetTestCasePropertyMap(TestCase test, string propertyName, I var values = new List(); foreach (var items in kvss) { - var map = new YamlMappingNode(items); - values.Add(map.ConvertScalarMapToTsvString(keys)); + var map = new YamlMappingNode(items!); + var tsv = map.ConvertScalarMapToTsvString(keys); + if (tsv != null) values.Add(tsv); } var combinedKey = new YamlScalarNode(string.Join("\t", keys)); @@ -327,7 +336,7 @@ private static void SetTestCasePropertyMap(TestCase test, string propertyName, I SetTestCaseProperty(test, propertyName, newMap.ToJsonString()); } - private static KeyValuePair NormalizeToScalarKeyValuePair(TestCase test, KeyValuePair item, string workingDirectory = null) + private static KeyValuePair NormalizeToScalarKeyValuePair(TestCase test, KeyValuePair item, string workingDirectory) { var key = item.Key; var keyOk = key is YamlScalarNode; @@ -335,7 +344,7 @@ private static KeyValuePair NormalizeToScalarKeyValuePair(Te var valueOk = value is YamlScalarNode; if (keyOk && valueOk) return item; - string[] keys = null; + string[]? keys = null; if (!keyOk) { var text = key.ConvertScalarSequenceToTsvString(); @@ -353,7 +362,7 @@ private static KeyValuePair NormalizeToScalarKeyValuePair(Te if (!valueOk) { - value = value.ConvertScalarSequenceToMultiLineTsvScalarNode(test, keys); + value = value.ConvertScalarSequenceToMultiLineTsvScalarNode(test, keys!); } else { @@ -363,12 +372,12 @@ private static KeyValuePair NormalizeToScalarKeyValuePair(Te value = fileContent; if (!(value is YamlScalarNode)) { - value = value.ConvertScalarSequenceToMultiLineTsvScalarNode(test, keys); + value = value.ConvertScalarSequenceToMultiLineTsvScalarNode(test, keys!); } } } - Logger.Log($"YamlTestCaseParser.NormalizeToScalarKeyValuePair: key='{(key as YamlScalarNode).Value}', value='{(value as YamlScalarNode).Value}'"); + Logger.Log($"YamlTestCaseParser.NormalizeToScalarKeyValuePair: key='{(key as YamlScalarNode)?.Value}', value='{(value as YamlScalarNode)?.Value}'"); return new KeyValuePair(key, value); } @@ -398,7 +407,7 @@ private static bool TryGetFileContentFromScalar(string scalar, string workingDir return false; } - private static string GetScalarString(YamlMappingNode mapping, Dictionary> tags, string mappingName, string defaultValue = null) + private static string? GetScalarString(YamlMappingNode? mapping, Dictionary> tags, string mappingName, string? defaultValue = null) { var value = GetScalarString(mapping, mappingName, null); if (value != null) return value; @@ -411,28 +420,17 @@ private static string GetScalarString(YamlMappingNode mapping, Dictionary !IsValidTestCaseNode((key as YamlScalarNode).Value)); + var invalid = mapping.Children.Keys.Where(key => !IsValidTestCaseNode((key as YamlScalarNode)?.Value)); if (invalid.Count() == 1 && command == null) { - var name = (invalid.FirstOrDefault() as YamlScalarNode).Value; + var name = (invalid.FirstOrDefault() as YamlScalarNode)?.Value; if (name == null) return null; command = GetScalarString(mapping, name); area = UpdateArea(mapping, area); - @class = GetScalarString(mapping, "class", @class); + @class = GetScalarString(mapping, "class", @class)!; return GetFullyQualifiedName(area, @class, name, stepNumber); } @@ -500,11 +498,10 @@ private static string UpdateWorkingDirectory(YamlMappingNode mapping, string cur return UpdateWorkingDirectory(currentWorkingDirectory, workingDirectory); } - private static string UpdateWorkingDirectory(string currentWorkingDirectory, string workingDirectory) + private static string UpdateWorkingDirectory(string currentWorkingDirectory, string? workingDirectory) { - return string.IsNullOrEmpty(workingDirectory) - ? currentWorkingDirectory - : PathHelpers.Combine(currentWorkingDirectory, workingDirectory); + if (string.IsNullOrEmpty(workingDirectory)) return currentWorkingDirectory; + return PathHelpers.Combine(currentWorkingDirectory, workingDirectory) ?? currentWorkingDirectory; } private const string defaultClassName = "TestCases"; diff --git a/src/extensions/testframework/YamlTestCaseRunner.cs b/src/extensions/testframework/YamlTestCaseRunner.cs index 27568172..b5a17999 100644 --- a/src/extensions/testframework/YamlTestCaseRunner.cs +++ b/src/extensions/testframework/YamlTestCaseRunner.cs @@ -80,11 +80,11 @@ private static IEnumerable TestCaseGetResults(TestCase test) var notExpect = YamlTestProperties.Get(test, "not-expect"); var env = YamlTestProperties.Get(test, "env"); var workingDirectory = YamlTestProperties.Get(test, "working-directory"); - var timeout = int.Parse(YamlTestProperties.Get(test, "timeout")); + var timeout = int.Parse(YamlTestProperties.Get(test, "timeout", YamlTestFramework.DefaultTimeout)!); var simulate = YamlTestProperties.Get(test, "simulate"); var skipOnFailure = YamlTestProperties.Get(test, "skipOnFailure") switch { "true" => true, _ => false }; - var basePath = new FileInfo(test.CodeFilePath).DirectoryName; + var basePath = new FileInfo(test.CodeFilePath).DirectoryName!; workingDirectory = Path.Combine(basePath, workingDirectory ?? ""); var tryCreateWorkingDirectory = !string.IsNullOrEmpty(workingDirectory) && !Directory.Exists(workingDirectory); if (tryCreateWorkingDirectory) Directory.CreateDirectory(workingDirectory); @@ -127,7 +127,7 @@ private static string GetTestResultDisplayName(string testDisplayName, string fo foreach(var property in foreachItemObject.EnumerateObject()) { var keys = property.Name.Split(new char[] { '\t' }); - var values = property.Value.GetString().Split(new char[] { '\t' }); + var values = property.Value.GetString()!.Split(new char[] { '\t' }); for (int i = 0; i < keys.Length; i++) { @@ -186,7 +186,7 @@ private static string RedactSensitiveDataFromForeachItem(string foreachItem) return Encoding.UTF8.GetString(stream.ToArray()); } - private static IEnumerable ExpandForEachGroups(string @foreach) + private static IEnumerable ExpandForEachGroups(string? @foreach) { var kvs = KeyValuePairsFromJson(@foreach, false) .Select(kv => new KeyValuePair>( @@ -220,15 +220,15 @@ private static Dictionary DupAndAdd(Dictionary d return dup; } - private static TestOutcome RunTestCase(TestCase test, bool skipOnFailure, string cli, string command, string script, bool scriptIsBash, string @foreach, string arguments, string input, string expect, string expectGpt, string notExpect, string env, string workingDirectory, int timeout, out string stdOut, out string stdErr, out string errorMessage, out string stackTrace, out string additional, out string debugTrace) + private static TestOutcome RunTestCase(TestCase test, bool skipOnFailure, string cli, string? command, string? script, bool scriptIsBash, string @foreach, string? arguments, string? input, string? expect, string? expectGpt, string? notExpect, string? env, string workingDirectory, int timeout, out string stdOut, out string stdErr, out string errorMessage, out string stackTrace, out string additional, out string debugTrace) { var outcome = TestOutcome.None; additional = $"START TIME: {DateTime.Now}"; debugTrace = ""; - stackTrace = script; + stackTrace = script ?? string.Empty; - List filesToDelete = null; + List? filesToDelete = null; var sbOut = new StringBuilder(); var sbErr = new StringBuilder(); @@ -263,6 +263,8 @@ private static TestOutcome RunTestCase(TestCase test, bool skipOnFailure, string UpdatePathEnvironment(startInfo); var process = Process.Start(startInfo); + if (process == null) throw new Exception("Process.Start() returned null!"); + process.StandardInput.WriteLine(input ?? string.Empty); process.StandardInput.Close(); @@ -321,7 +323,7 @@ private static TestOutcome RunTestCase(TestCase test, bool skipOnFailure, string : outcome; } - private static List> ConvertValuesToAtArgs(List> kvs, ref List files) + private static List> ConvertValuesToAtArgs(List> kvs, ref List? files) { var newList = new List>(); foreach (var item in kvs) @@ -340,7 +342,7 @@ private static List> ConvertValuesToAtArgs(List> KeyValuePairsFromJson(string json, bool allowSimpleString) + private static List> KeyValuePairsFromJson(string? json, bool allowSimpleString) { var kvs = new List>(); if (!string.IsNullOrEmpty(json)) @@ -352,7 +354,7 @@ private static List> KeyValuePairsFromJson(string j { // if it's a simple string, there is no "key" for the argument... pass it as value with an empty string as key // this will ensure that an additional '--' isn't emitted preceding the string-only arguments - kvs.Add(new KeyValuePair("", parsed.GetString())); + kvs.Add(new KeyValuePair("", parsed.GetString() ?? string.Empty)); } else if (parsed.ValueKind != JsonValueKind.Object) { @@ -363,14 +365,14 @@ private static List> KeyValuePairsFromJson(string j { foreach (var item in parsed.EnumerateObject()) { - kvs.Add(new KeyValuePair(item.Name, item.Value.GetString())); + kvs.Add(new KeyValuePair(item.Name, item.Value.GetString() ?? string.Empty)); } } } return kvs; } - private static string UpdateStackTrace(string stackTrace, string command, List> kvs) + private static string UpdateStackTrace(string stackTrace, string? command, List> kvs) { if (command?.EndsWith("dev shell") ?? false) { @@ -381,7 +383,7 @@ private static string UpdateStackTrace(string stackTrace, string command, List !string.IsNullOrEmpty(kv.Key)) .Select(kv => $"{kv.Key}:\n{kv.Value.Replace("\n", "\n ")}")); stackTrace = !string.IsNullOrEmpty(commandArguments) - ? $"{stackTrace ?? string.Empty}\nCOMMAND: {command}\n{commandArguments}".Trim('\r', '\n', ' ') - : $"{stackTrace ?? string.Empty}\nCOMMAND: {command}".Trim('\r', '\n', ' '); + ? $"{stackTrace}\nCOMMAND: {command}\n{commandArguments}".Trim('\r', '\n', ' ') + : $"{stackTrace}\nCOMMAND: {command}".Trim('\r', '\n', ' '); } return stackTrace; } - private static string WriteMultilineTsvToTempFile(string text, ref List files) + private static string WriteMultilineTsvToTempFile(string text, ref List? files) { files ??= new List(); @@ -421,7 +423,7 @@ private static string WriteMultilineTsvToTempFile(string text, ref List continue; } - var newValue = WriteTextToTempFile(value.Replace('\f', '\n')); + var newValue = WriteTextToTempFile(value.Replace('\f', '\n'))!; files.Add(newValue); newValues.Add($"@{newValue}"); @@ -432,11 +434,11 @@ private static string WriteMultilineTsvToTempFile(string text, ref List var newText = string.Join("\n", newLines); var file = WriteTextToTempFile(newText); - files.Add(file); - return file; + files.Add(file!); + return file!; } - private static string WriteTextToTempFile(string text, string extension = null) + private static string? WriteTextToTempFile(string? text, string? extension = null) { if (!string.IsNullOrEmpty(text)) { @@ -489,7 +491,7 @@ private static string FindCli(string cli) } } - private static string FindCliOrNull(string cli) + private static string? FindCliOrNull(string cli) { var dll = $"{cli}.dll"; var exe = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? $"{cli}.exe" : cli; @@ -521,15 +523,15 @@ private static string FindCliOrNull(string cli) return null; } - private static string FindCliDllOrNull(string cli, string dll) + private static string? FindCliDllOrNull(string cli, string dll) { var fi = new FileInfo(cli); if (!fi.Exists) return null; - var check = Path.Combine(fi.DirectoryName, dll); + var check = Path.Combine(fi.DirectoryName!, dll); if (File.Exists(check)) return check; - var matches = fi.Directory.GetFiles(dll, SearchOption.AllDirectories); + var matches = fi.Directory!.GetFiles(dll, SearchOption.AllDirectories); if (matches.Length == 1) return matches.First().FullName; return null; @@ -548,9 +550,9 @@ private static string CliNotFound(string cli) return cli; } - private static string PickCliOrNull(IEnumerable clis) + private static string? PickCliOrNull(IEnumerable clis) { - var cliOrNulls = new List(); + var cliOrNulls = new List(); foreach (var cli in clis) { cliOrNulls.Add(FindCliOrNull(cli)); @@ -604,12 +606,12 @@ private static IEnumerable GetPossibleRunTimeLocations() return new string[]{ "" }; } - private static void UpdateEnvironment(ProcessStartInfo startInfo, string envAsMultiLineString) + private static void UpdateEnvironment(ProcessStartInfo startInfo, string? envAsMultiLineString) { var ok = !string.IsNullOrEmpty(envAsMultiLineString); if (!ok) return; - var env = YamlEnvHelpers.GetEnvironmentFromMultiLineString(envAsMultiLineString); + var env = YamlEnvHelpers.GetEnvironmentFromMultiLineString(envAsMultiLineString!); foreach (var item in env) { startInfo.Environment[item.Key] = item.Value; @@ -624,8 +626,8 @@ static void UpdatePathEnvironment(ProcessStartInfo startInfo) var dll = FindCliDllOrNull(cli.FullName, cli.Name.Replace(".exe", "") + ".dll"); if (dll != null) { - var cliPath = cli.Directory.FullName; - var dllPath = new FileInfo(dll).Directory.FullName; + var cliPath = cli.Directory!.FullName; + var dllPath = new FileInfo(dll).Directory!.FullName; var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var pathVar = isWindows ? "PATH" : "LD_LIBRARY_PATH"; @@ -702,7 +704,7 @@ private static bool WaitForExit(Process process, int timeout) return completed; } - private static void GetStartInfoArgs(out string startProcess, out string startArgs,string cli, string command, string script, bool scriptIsBash, List> kvs, string expect, string notExpect, ref List files) + private static void GetStartInfoArgs(out string startProcess, out string startArgs,string cli, string? command, string? script, bool scriptIsBash, List> kvs, string? expect, string? notExpect, ref List? files) { startProcess = FindCacheCli(cli); @@ -714,7 +716,7 @@ private static void GetStartInfoArgs(out string startProcess, out string startAr var hasExpectations = !string.IsNullOrEmpty(expect) || !string.IsNullOrEmpty(notExpect); if (hasExpectations) { - command = WriteTextToTempFile(command); + command = WriteTextToTempFile(command)!; files ??= new List(); files.Add(command); @@ -769,7 +771,7 @@ private static string FindGitBashExe() return found.Where(x => x.ToLower().Contains("git")).FirstOrDefault() ?? "bash.exe"; } - private static string GetAtArgs(string expect, string notExpect) + private static string GetAtArgs(string? expect, string? notExpect) { var atArgs = $""; if (!string.IsNullOrEmpty(expect)) atArgs += $" --expect @{expect}"; @@ -807,7 +809,7 @@ private static string GetKeyValueArgs(List> kvs) return args.ToString().TrimEnd(); } - private static TestOutcome SimulateTestCase(TestCase test, string simulate, string cli, string command, string script, bool scriptIsBash, string @foreach, string arguments, string input, string expect, string expectGpt, string notExpect, string env, string workingDirectory, out string stdOut, out string stdErr, out string errorMessage, out string stackTrace, out string additional, out string debugTrace) + private static TestOutcome SimulateTestCase(TestCase test, string simulate, string cli, string? command, string? script, bool scriptIsBash, string @foreach, string? arguments, string? input, string? expect, string? expectGpt, string? notExpect, string? env, string workingDirectory, out string stdOut, out string stdErr, out string errorMessage, out string stackTrace, out string additional, out string debugTrace) { var sb = new StringBuilder(); sb.AppendLine($"cli='{cli?.Replace("\n", "\\n")}'"); @@ -831,9 +833,9 @@ private static TestOutcome SimulateTestCase(TestCase test, string simulate, stri var outcome = OutcomeFromString(simulate); if (outcome == TestOutcome.Passed) { - stdErr = null; - debugTrace = null; - errorMessage = null; + stdErr = string.Empty; + debugTrace = string.Empty; + errorMessage = string.Empty; } return outcome; @@ -909,7 +911,7 @@ private static string ExtraDebugInfo() var variables = Environment.GetEnvironmentVariables(); var keys = new List(variables.Count); - foreach (var key in variables.Keys) keys.Add(key as string); + foreach (var key in variables.Keys) keys.Add((key as string)!); keys.Sort(); foreach (var key in keys) @@ -948,7 +950,7 @@ private static TestOutcome ExpectGptOutcome(string output, string expect, string question.AppendLine("You **must always** answer \"PASS\" if the expectation is met."); question.AppendLine("You **must always** answer \"FAIL\" if the expectation is not met."); question.AppendLine("You **must only** answer \"PASS\" or \"FAIL\"."); - var questionTempFile = WriteTextToTempFile(question.ToString()); + var questionTempFile = WriteTextToTempFile(question.ToString())!; try { @@ -965,6 +967,7 @@ private static TestOutcome ExpectGptOutcome(string output, string expect, string Logger.Log($"ExpectGptOutcome: Process.Start('{startProcess} {startArgs}')"); var process = Process.Start(startInfo); + if (process == null) throw new Exception("Process.Start() returned null!"); process.StandardInput.Close(); var outDoneSignal = new ManualResetEvent(false); diff --git a/src/extensions/testframework/YamlTestConfigHelpers.cs b/src/extensions/testframework/YamlTestConfigHelpers.cs index 49e5045a..969467d5 100644 --- a/src/extensions/testframework/YamlTestConfigHelpers.cs +++ b/src/extensions/testframework/YamlTestConfigHelpers.cs @@ -10,7 +10,7 @@ namespace Azure.AI.Details.Common.CLI.TestFramework { public class YamlTestConfigHelpers { - public static FileInfo FindTestConfigFile(DirectoryInfo checkHereAndParents) + public static FileInfo? FindTestConfigFile(DirectoryInfo checkHereAndParents) { Logger.Log($"YamlTestConfigHelpers.GetTestConfigFile: Looking for test config file in {checkHereAndParents.FullName}"); @@ -38,9 +38,9 @@ public static DirectoryInfo GetTestDirectory(DirectoryInfo checkHereAndParents) var testDirectory = tags["testDirectory"].FirstOrDefault(); if (testDirectory != null) { - testDirectory = PathHelpers.Combine(file.Directory.FullName, testDirectory); + testDirectory = PathHelpers.Combine(file.Directory!.FullName, testDirectory); Logger.Log($"YamlTestConfigHelpers.GetTestDirectory: Found test directory in config file at {testDirectory}"); - return new DirectoryInfo(testDirectory); + return new DirectoryInfo(testDirectory!); } } } @@ -54,9 +54,9 @@ public static DirectoryInfo GetTestDirectory(DirectoryInfo checkHereAndParents) var testDirectory = tags["testDirectory"].FirstOrDefault(); if (testDirectory != null) { - testDirectory = PathHelpers.Combine(file.Directory.FullName, testDirectory); + testDirectory = PathHelpers.Combine(file.Directory!.FullName, testDirectory); Logger.Log($"YamlTestConfigHelpers.GetTestDirectory: Found test directory in default tags file at {testDirectory}"); - return new DirectoryInfo(testDirectory); + return new DirectoryInfo(testDirectory!); } } } diff --git a/src/extensions/testframework/YamlTestFramework.csproj b/src/extensions/testframework/YamlTestFramework.csproj index 67f2822b..74676422 100644 --- a/src/extensions/testframework/YamlTestFramework.csproj +++ b/src/extensions/testframework/YamlTestFramework.csproj @@ -2,6 +2,7 @@ net8.0 + enable diff --git a/src/extensions/testframework/YamlTestFrameworkConsoleHost.cs b/src/extensions/testframework/YamlTestFrameworkConsoleHost.cs index ab7c6940..6b612f53 100644 --- a/src/extensions/testframework/YamlTestFrameworkConsoleHost.cs +++ b/src/extensions/testframework/YamlTestFrameworkConsoleHost.cs @@ -42,7 +42,7 @@ public void RecordEnd(TestCase testCase, TestOutcome outcome) _testRun.EndTest(testCase, outcome); } - public bool Finish(IDictionary> resultsByTestCaseId, string outputResultsFormat = "trx", string outputResultsFile = null) + public bool Finish(IDictionary> resultsByTestCaseId, string outputResultsFormat = "trx", string? outputResultsFile = null) { _testRun.EndRun(); @@ -163,7 +163,7 @@ private void PrintResult(TestResult testResult) var hasStdErr = !string.IsNullOrEmpty(stdErr); if (hasStdErr) { - var lines = stdErr.Split('\n'); + var lines = stdErr!.Split('\n'); if (lines.Length > 10) { var first5 = lines.Take(5); diff --git a/src/extensions/testframework/YamlTestProperties.cs b/src/extensions/testframework/YamlTestProperties.cs index ee496e75..1cdd3f6f 100644 --- a/src/extensions/testframework/YamlTestProperties.cs +++ b/src/extensions/testframework/YamlTestProperties.cs @@ -26,7 +26,7 @@ public static void Set(TestCase test, string name, string value) } } - public static string Get(TestCase test, string name, string defaultValue = null) + public static string? Get(TestCase test, string name, string? defaultValue = null) { var value = test.GetPropertyValue(properties[name], defaultValue); Logger.LogIf(!string.IsNullOrEmpty(value), $"TestCaseProperties.Get('{name}') = '{value?.Replace("\n", "\\n")}'");