From af3294875660406739e14fb67bf3f9a524206627 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Thu, 30 Jan 2025 21:03:15 +1000 Subject: [PATCH] Add Analyzer to warn about LINQ calls on string receivers --- .global.editorconfig.ini | 2 + .../AnalyzersCommon/RoslynUtils.cs | 9 ++ .../ExprBodiedMemberFlowAnalyzer.cs | 2 + .../BizHawk.Analyzer/LINQOnStringsAnalyzer.cs | 137 ++++++++++++++++++ .../LINQOnStringsAnalyzerTests.cs | 91 ++++++++++++ References/BizHawk.Analyzer.dll | Bin 45056 -> 51712 bytes .../cheats/GbaGameSharkDecoder.cs | 3 +- .../lua/LuaDocumentation.cs | 2 +- .../movie/import/DsmImport.cs | 4 +- .../tools/HexEditor/HexEditor.cs | 2 +- .../tools/Lua/LuaConsole.cs | 7 +- .../vpads_schemata/PSXSchema.cs | 3 +- .../vpads_schemata/PceSchema.cs | 2 +- .../vpads_schemata/PcfxSchema.cs | 3 +- .../vpads_schemata/SaturnSchema.cs | 2 +- .../vpads_schemata/SnesSchema.cs | 2 +- 16 files changed, 253 insertions(+), 18 deletions(-) create mode 100644 ExternalProjects/BizHawk.Analyzer/LINQOnStringsAnalyzer.cs create mode 100644 ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/LINQOnStringsAnalyzerTests.cs diff --git a/.global.editorconfig.ini b/.global.editorconfig.ini index 41faa9de5e..c1c019d77c 100644 --- a/.global.editorconfig.ini +++ b/.global.editorconfig.ini @@ -47,6 +47,8 @@ dotnet_diagnostic.BHI1210.severity = error dotnet_diagnostic.BHI3100.severity = error # Use .Order()/.OrderDescending() shorthand dotnet_diagnostic.BHI3101.severity = warning +# Prefer specialised methods over LINQ on string receivers +dotnet_diagnostic.BHI3102.severity = error # Throw NotImplementedException from methods/props marked [FeatureNotImplemented] dotnet_diagnostic.BHI3300.severity = error diff --git a/ExternalProjects/AnalyzersCommon/RoslynUtils.cs b/ExternalProjects/AnalyzersCommon/RoslynUtils.cs index cc8b60d094..40b12e569e 100644 --- a/ExternalProjects/AnalyzersCommon/RoslynUtils.cs +++ b/ExternalProjects/AnalyzersCommon/RoslynUtils.cs @@ -1,8 +1,11 @@ namespace BizHawk.Analyzers; +using System.Threading; + using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Operations; public static class RoslynUtils { @@ -24,6 +27,12 @@ public static class RoslynUtils public static ITypeSymbol? GetThrownExceptionType(this SemanticModel model, ThrowStatementSyntax tss) => model.GetThrownExceptionType(tss.Expression!); + public static TypeInfo GetTypeInfo(this SemanticModel model, IArgumentOperation argOp, CancellationToken cancellationToken) + { + var syn = argOp.Syntax; + return model.GetTypeInfo(syn is ArgumentSyntax argSyn ? argSyn.Expression : syn, cancellationToken); + } + public static bool Matches(this ISymbol expected, ISymbol? actual) => SymbolEqualityComparer.Default.Equals(expected, actual); diff --git a/ExternalProjects/BizHawk.Analyzer/ExprBodiedMemberFlowAnalyzer.cs b/ExternalProjects/BizHawk.Analyzer/ExprBodiedMemberFlowAnalyzer.cs index 63ffcf1d7d..58d2fbcd13 100644 --- a/ExternalProjects/BizHawk.Analyzer/ExprBodiedMemberFlowAnalyzer.cs +++ b/ExternalProjects/BizHawk.Analyzer/ExprBodiedMemberFlowAnalyzer.cs @@ -115,7 +115,9 @@ public sealed class ExprBodiedMemberFlowAnalyzer : DiagnosticAnalyzer Fail(); return; } +#pragma warning disable BHI3102 // LINQ `Contains(char)` is fine here var hasLineBreakAfterArrow = aecs.ArrowToken.HasTrailingTrivia && aecs.ArrowToken.TrailingTrivia.ToFullString().Contains('\n'); +#pragma warning restore BHI3102 if ((hasLineBreakAfterArrow ? '\n' : ' ') != expectedWhitespace.After) Fail(); }, SyntaxKind.ArrowExpressionClause); diff --git a/ExternalProjects/BizHawk.Analyzer/LINQOnStringsAnalyzer.cs b/ExternalProjects/BizHawk.Analyzer/LINQOnStringsAnalyzer.cs new file mode 100644 index 0000000000..065e2625e5 --- /dev/null +++ b/ExternalProjects/BizHawk.Analyzer/LINQOnStringsAnalyzer.cs @@ -0,0 +1,137 @@ +namespace BizHawk.Analyzers; + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class LINQOnStringsAnalyzer : DiagnosticAnalyzer +{ + private static readonly DiagnosticDescriptor DiagLINQOnStrings = new( + id: "BHI3102", + title: "Prefer specialised methods over LINQ on string receivers", + messageFormat: "{0}", + category: "Usage", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(DiagLINQOnStrings); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction(initContext => + { + const string CHAR_ZERO_WARNING = " (but did you intend to get `default(char)`?)"; + static string DisambigNameFor(IMethodSymbol sym) + => $"{sym.Name}#{sym.Parameters.Length}"; +// var hasHawkStringExtensions = initContext.Compilation.GetTypeByMetadataName("BizHawk.Common.StringExtensions.StringExtensions") is not null; + var hasStringContainsChar = initContext.Compilation.GetSpecialType(SpecialType.System_String) + .GetMembers("Contains").Length > 1; + var linqMethodSyms = initContext.Compilation.GetTypeByMetadataName("System.Linq.Enumerable")!.GetMembers(); + Dictionary banned = new(); + foreach (var (identifier, msgFmtStr) in new[] + { + ("Append", "Use concatenation or interpolation"), + ("Concat", "Use concatenation operator"), // we have special handling for when the "other" string is only `IEnumerable` + ("ElementAt", "Use `({0})[i]`"), + ("ElementAtOrDefault", "Use `i < str.Length ? str[i] : default`" + CHAR_ZERO_WARNING), + ("Prepend", "Use concatenation or interpolation"), + ("Skip", "Use `({0}).Substring(offset)` (or `.AsSpan(offset)`)"), + ("Take", "Use `({0}).Substring(0, count)` (or `.AsSpan(0, count)`)"), + ("ToArray", "Use `({0}).ToCharArray()`"), + }) + { + // only one overload, simply add to list + var foundSym = linqMethodSyms.OfType().FirstOrDefault(sym => sym.Name == identifier); + if (foundSym is not null) banned[DisambigNameFor(foundSym)] = (foundSym, DiagnosticSeverity.Warning, msgFmtStr); + } + foreach (var (identifier, msgFmtStr) in new[] + { + ("Any", "Use `({0}).Length is not 0`"), + ("Count", "Use `({0}).Length`"), + ("First", "Use `({0})[0]`"), + ("FirstOrDefault", "Use `str.Length is 0 ? default : str[0]`" + CHAR_ZERO_WARNING), + ("Last", "Use `({0})[^1]`"), + ("LastOrDefault", "Use `str.Length is 0 ? default : str[^1]`" + CHAR_ZERO_WARNING), + ("LongCount", "Use `(long) ({0}).Length` (`String` cannot exceed `int.MaxValue` chars)"), + ("Single", "Use `str[0]`, asserting `str.Length is 1` beforehand if desired"), + ("SingleOrDefault", "Use `str.Length is 1 ? str[0] : default`" + CHAR_ZERO_WARNING), + }) + { + // for these, the overload with a delegate param (combined `Where`) is allowed, and the overload without is banned + var foundSym = linqMethodSyms.OfType() + .FirstOrDefault(sym => sym.Parameters.Length is 1 && sym.Name == identifier); + if (foundSym is not null) banned[DisambigNameFor(foundSym)] = (foundSym, DiagnosticSeverity.Error, msgFmtStr); + } + var linqBinaryContainsSym = linqMethodSyms.OfType() + .FirstOrDefault(static sym => sym.Parameters.Length is 2 && sym.Name is "Contains"); + if (linqBinaryContainsSym is not null) + { + banned[DisambigNameFor(linqBinaryContainsSym)] = ( + linqBinaryContainsSym, + DiagnosticSeverity.Error, + "Call the instance method from `String` (why would you do this)"); + } + foreach (var sym in linqMethodSyms.OfType().Where(static sym => sym.Name is "DefaultIfEmpty")) + { + banned[DisambigNameFor(sym)] = sym.Parameters.Length is 2 + ? (sym, DiagnosticSeverity.Warning, "Use `str.Length is 0 ? [ defaultValue ] : str`") + : (sym, DiagnosticSeverity.Error, "Use `str.Length is 0 ? [ default(char) ] : str`" + CHAR_ZERO_WARNING); + } + var linqReverseSym = linqMethodSyms.OfType().FirstOrDefault(static sym => sym.Name is "Reverse"); + if (linqReverseSym is not null) + { + banned[DisambigNameFor(linqReverseSym)] = ( + linqReverseSym, + DiagnosticSeverity.Error, + "This will reverse the order of `char`s, which are NOT Unicode graphemes or even codepoints, and thus the result may be malformed;" + + " to reverse text, use `str.EnumerateRunes().Reverse()` (.NET Core) or `Strings.StrReverse(str)` (from VB.NET helpers)," + + " and to reverse a list of 16-bit values, use `Array.Reverse` on a `char[]`/`ushort[]`"); + } + initContext.RegisterOperationAction( + oac => + { + var operation = (IInvocationOperation) oac.Operation; + var calledSym = operation.TargetMethod.ConstructedFrom; + var disambigName = DisambigNameFor(calledSym); + if (!banned.TryGetValue(disambigName, out var tuple)) return; + var (symToMatch, level, msgFmtStr) = tuple; + if (!symToMatch.Matches(calledSym)) return; + var receiverExpr = operation.Arguments[0]; + var receiverExprType = operation.SemanticModel!.GetTypeInfo(receiverExpr, oac.CancellationToken).Type!; + if (receiverExprType.SpecialType is not SpecialType.System_String) return; + switch (disambigName) + { + case "Concat#2" /*when operation.SemanticModel! + .GetTypeInfo(operation.Arguments[1], oac.CancellationToken) + .Type!.SpecialType is not SpecialType.System_String*/: + // other string is only `IEnumerable` + level = DiagnosticSeverity.Warning; + msgFmtStr = "Use concatenation if both are strings and the value is being enumerated to a new string"; + break; + case "Contains#1" when !hasStringContainsChar: + level = DiagnosticSeverity.Warning; + var arg = operation.Arguments[1].ConstantValue; + msgFmtStr = arg.HasValue + ? $"Use `({{0}}).Contains(\"{arg.Value}\")`" + : "Use `str.Contains(c.ToString())`"; + break; + } + oac.ReportDiagnostic(Diagnostic.Create( + DiagLINQOnStrings, + operation.Syntax.GetLocation(), + level, + additionalLocations: null, + properties: null, + messageArgs: string.Format(msgFmtStr, receiverExpr.Syntax))); + }, + OperationKind.Invocation); + }); + } +} diff --git a/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/LINQOnStringsAnalyzerTests.cs b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/LINQOnStringsAnalyzerTests.cs new file mode 100644 index 0000000000..9ed20daf72 --- /dev/null +++ b/ExternalProjects/BizHawk.AnalyzersTests/BizHawk.Analyzer/LINQOnStringsAnalyzerTests.cs @@ -0,0 +1,91 @@ +namespace BizHawk.Tests.Analyzers; + +using System.Threading.Tasks; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier< + BizHawk.Analyzers.LINQOnStringsAnalyzer, + Microsoft.CodeAnalysis.Testing.DefaultVerifier>; + +[TestClass] +public sealed class LINQOnStringsAnalyzerTests +{ + [TestMethod] + public Task CheckMisuseOfLINQOnStrings() + => Verify.VerifyAnalyzerAsync(""" + using System.Collections.Generic; + using System.Linq; + public static class Cases { + private static bool DummyPredicate(char c) + => c is >= 'a' and <= 'z'; + private static char ZQ(string str) + => str.SingleOrDefault(DummyPredicate); + private static char ZR(string str) + => str.Single(DummyPredicate); + private static long ZS(string str) + => str.LongCount(DummyPredicate); + private static char ZT(string str) + => str.LastOrDefault(DummyPredicate); + private static char ZU(string str) + => str.Last(DummyPredicate); + private static char ZV(string str) + => str.FirstOrDefault(DummyPredicate); + private static char ZW(string str) + => str.First(DummyPredicate); + private static int ZX(string str) + => str.Count(DummyPredicate); + private static bool ZY(string str) + => str.Any(DummyPredicate); + private static bool ZZ(string str) + => str.All(DummyPredicate); + private static bool AA(string str) + => {|BHI3102:str.Any()|}; + private static IEnumerable AB(string str) + => {|BHI3102:str.Append('.')|}; + private static IEnumerable AC(string str) + => {|BHI3102:str.Concat("-_-")|}; + private static IEnumerable AD(string str) + => {|BHI3102:str.Concat(new[] { '-', '_', '-' })|}; + private static bool AE(string str) + => {|BHI3102:Enumerable.Contains(str, '.')|}; + private static int AF(string str) + => {|BHI3102:str.Count()|}; + private static IEnumerable AG(string str) + => {|BHI3102:str.DefaultIfEmpty()|}; + private static IEnumerable AH(string str) + => {|BHI3102:str.DefaultIfEmpty('.')|}; + private static char AI(string str) + => {|BHI3102:str.ElementAt(2)|}; + private static char AJ(string str) + => {|BHI3102:str.ElementAtOrDefault(2)|}; + private static char AK(string str) + => {|BHI3102:str.First()|}; + private static char AL(string str) + => {|BHI3102:str.FirstOrDefault()|}; + private static char AM(string str) + => {|BHI3102:str.Last()|}; + private static char AN(string str) + => {|BHI3102:str.LastOrDefault()|}; + private static long AO(string str) + => {|BHI3102:str.LongCount()|}; + private static IEnumerable AP(string str) + => {|BHI3102:str.Prepend('.')|}; + private static IEnumerable AQ(string str) + => {|BHI3102:str.Reverse()|}; + private static char AR(string str) + => {|BHI3102:str.Single()|}; + private static char AS(string str) + => {|BHI3102:str.SingleOrDefault()|}; + private static IEnumerable AT(string str) + => {|BHI3102:str.Skip(2)|}; + private static IEnumerable AU(string str) + => {|BHI3102:str.Take(2)|}; + private static char[] AV(string str) + => {|BHI3102:str.ToArray()|}; + } + namespace BizHawk.Common.StringExtensions { + public static class StringExtensions {} // Analyzer does more checks if this exists + } + """); +} diff --git a/References/BizHawk.Analyzer.dll b/References/BizHawk.Analyzer.dll index c2a3441baa64f20bbaf1a3cb2537853b8277771c..2b383fabf22217ba1d139fa7ab9fc59900812b4d 100644 GIT binary patch literal 51712 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 diff --git a/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs b/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs index b65d3f42a4..031bc12019 100644 --- a/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs +++ b/src/BizHawk.Client.Common/cheats/GbaGameSharkDecoder.cs @@ -1,5 +1,4 @@ using System.Globalization; -using System.Linq; #pragma warning disable MA0089 namespace BizHawk.Client.Common.cheats @@ -64,7 +63,7 @@ namespace BizHawk.Client.Common.cheats var result = new DecodeResult { - Size = code.First() switch + Size = code[0] switch { '0' => WatchSize.Byte, '1' => WatchSize.Word, diff --git a/src/BizHawk.Client.Common/lua/LuaDocumentation.cs b/src/BizHawk.Client.Common/lua/LuaDocumentation.cs index a2ed3a5209..ddcd19206e 100644 --- a/src/BizHawk.Client.Common/lua/LuaDocumentation.cs +++ b/src/BizHawk.Client.Common/lua/LuaDocumentation.cs @@ -146,7 +146,7 @@ namespace BizHawk.Client.Common var sb = new StringBuilder(); - if (f.ParameterList.Any()) + if (f.ParameterList.Length is not 0) { sb .Append($"{f.Library}.{f.Name}("); diff --git a/src/BizHawk.Client.Common/movie/import/DsmImport.cs b/src/BizHawk.Client.Common/movie/import/DsmImport.cs index a251895c98..021de6ec30 100644 --- a/src/BizHawk.Client.Common/movie/import/DsmImport.cs +++ b/src/BizHawk.Client.Common/movie/import/DsmImport.cs @@ -1,5 +1,5 @@ using System.Globalization; -using System.Linq; + using BizHawk.Common; using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; @@ -109,7 +109,7 @@ namespace BizHawk.Client.Common if (sections.Length > 1) { - var mnemonics = sections[1].Take(_buttons.Length).ToList(); + var mnemonics = sections[1].AsSpan(start: 0, length: _buttons.Length); controller["Right"] = mnemonics[0] != '.'; controller["Left"] = mnemonics[1] != '.'; diff --git a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index 9203bc34a1..8eaff9f450 100644 --- a/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/src/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -1246,7 +1246,7 @@ namespace BizHawk.Client.EmuHawk } var parts = line.Split('='); - _textTable.Add(int.Parse(parts[0], NumberStyles.HexNumber), parts[1].First()); + _textTable.Add(int.Parse(parts[0], NumberStyles.HexNumber), parts[1][0]); } return true; diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index 3b2aef6da5..f0dcc800c9 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -1205,11 +1205,8 @@ namespace BizHawk.Client.EmuHawk private void ConsoleContextMenu_Opening(object sender, CancelEventArgs e) { RegisteredFunctionsContextItem.Enabled = LuaImp.RegisteredFunctions.Any(); - CopyContextItem.Enabled = OutputBox.SelectedText.Any(); - ClearConsoleContextItem.Enabled = - SelectAllContextItem.Enabled = - OutputBox.Text.Any(); - + CopyContextItem.Enabled = OutputBox.SelectedText.Length is not 0; + ClearConsoleContextItem.Enabled = SelectAllContextItem.Enabled = OutputBox.Text.Length is not 0; ClearRegisteredFunctionsLogContextItem.Enabled = LuaImp.RegisteredFunctions.Any(); } diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs index c02d6f1d03..4fd98815c2 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PSXSchema.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Drawing; -using System.Linq; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -48,7 +47,7 @@ namespace BizHawk.Emulation.Cores { foreach (var result in nyma.ActualPortData) { - var num = int.Parse(result.Port.ShortName.Last().ToString()); + var num = int.Parse(result.Port.ShortName[^1].ToString()); var device = result.Device.ShortName; if (device is "none") continue; yield return device switch diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs index 29c510c9e4..e0c06eff6e 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PceSchema.cs @@ -87,7 +87,7 @@ namespace BizHawk.Emulation.Cores { foreach (NymaCore.PortResult result in nyma.ActualPortData) { - var num = int.Parse(result.Port.ShortName.Last().ToString()); + var num = int.Parse(result.Port.ShortName[^1].ToString()); var device = result.Device.ShortName; if (device == "gamepad") { diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs index 0b5b4d22ce..bca1db7783 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/PcfxSchema.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Drawing; -using System.Linq; using BizHawk.Common; using BizHawk.Emulation.Common; @@ -21,7 +20,7 @@ namespace BizHawk.Emulation.Cores { foreach (NymaCore.PortResult result in nyma.ActualPortData) { - var num = int.Parse(result.Port.ShortName.Last().ToString()); + var num = int.Parse(result.Port.ShortName[^1].ToString()); var device = result.Device.ShortName; if (device == "gamepad") { diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs index b751b22de7..1d316ccbcc 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SaturnSchema.cs @@ -19,7 +19,7 @@ namespace BizHawk.Emulation.Cores foreach (var result in nyma.ActualPortData .Where(r => r.Port.ShortName != "builtin")) { - var num = int.Parse(result.Port.ShortName.Last().ToString()); + var num = int.Parse(result.Port.ShortName[^1].ToString()); var device = result.Device.ShortName; var schema = GenerateSchemaForPort(device, num, showMessageBox); if (schema != null) diff --git a/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs b/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs index 89be3c8231..0491d5a433 100644 --- a/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs +++ b/src/BizHawk.Emulation.Cores/vpads_schemata/SnesSchema.cs @@ -176,7 +176,7 @@ namespace BizHawk.Emulation.Cores { foreach (NymaCore.PortResult result in nyma.ActualPortData) { - var num = int.Parse(result.Port.ShortName.Last().ToString()); + var num = int.Parse(result.Port.ShortName[^1].ToString()); var device = result.Device.ShortName; if (device == "gamepad") {