From 000d12d237f147cf3b041adfa9dc8368e4d401c0 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Fri, 12 Jan 2024 15:47:50 -0600 Subject: [PATCH] C#: Enforce Globalization code quality rules --- modules/mono/.editorconfig | 9 ---- .../GodotBuildLogger.cs | 2 +- .../GodotTools.Core/StringExtensions.cs | 2 +- .../ForwarderMessageHandler.cs | 5 ++- .../DotNetSolution.cs | 12 ++--- .../GodotTools/GodotTools/Build/BuildInfo.cs | 27 +++++------ .../GodotTools/Build/BuildProblemsFilter.cs | 3 +- .../GodotTools/Build/BuildProblemsView.cs | 31 ++++++------- .../GodotTools/Export/ExportPlugin.cs | 9 ++-- .../GodotTools/GodotTools/GodotSharpEditor.cs | 9 ++-- .../GodotTools/Internals/GodotSharpDirs.cs | 2 +- .../editor/GodotTools/GodotTools/Utils/OS.cs | 4 +- .../glue/GodotSharp/GodotSharp/Core/Color.cs | 13 +++--- .../GodotSharp/Core/DelegateUtils.cs | 7 +-- .../GodotSharp/Core/GodotObject.exceptions.cs | 5 ++- .../glue/GodotSharp/GodotSharp/Core/Plane.cs | 2 + .../GodotSharp/GodotSharp/Core/Projection.cs | 2 + .../GodotSharp/GodotSharp/Core/Quaternion.cs | 2 + .../GodotSharp/Core/StringExtensions.cs | 45 +++++++------------ .../GodotSharp/GodotSharp/Core/Vector2.cs | 2 + .../GodotSharp/GodotSharp/Core/Vector2I.cs | 2 + .../GodotSharp/GodotSharp/Core/Vector3.cs | 2 + .../GodotSharp/GodotSharp/Core/Vector3I.cs | 2 + .../GodotSharp/GodotSharp/Core/Vector4.cs | 2 + .../GodotSharp/GodotSharp/Core/Vector4I.cs | 4 +- 25 files changed, 105 insertions(+), 100 deletions(-) diff --git a/modules/mono/.editorconfig b/modules/mono/.editorconfig index 9434d0693c02..db8fb2921cee 100644 --- a/modules/mono/.editorconfig +++ b/modules/mono/.editorconfig @@ -30,14 +30,5 @@ dotnet_diagnostic.CA1720.severity = none # CA1805: Do not initialize unnecessarily # Don't tell me what to do. dotnet_diagnostic.CA1805.severity = none -# CA1304: Specify CultureInfo -# TODO: We should look into this. -dotnet_diagnostic.CA1304.severity = warning -# CA1305: Specify IFormatProvider -# TODO: We should look into this. Disabled for now because it's annoying. -dotnet_diagnostic.CA1305.severity = none -# CA1310: Specify StringComparison for correctness -# TODO: We should look into this. Disabled for now because it's annoying. -dotnet_diagnostic.CA1310.severity = none # Diagnostics to prevent defensive copies of `in` struct parameters resharper_possibly_impure_method_call_on_readonly_variable_highlighting = error diff --git a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs index 3c46079414af..b699765b8eeb 100644 --- a/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs +++ b/modules/mono/editor/GodotTools/GodotTools.BuildLogger/GodotBuildLogger.cs @@ -165,7 +165,7 @@ public static string CsvEscape(this string value, char delimiter = ',') bool hasSpecialChar = value.IndexOfAny(new[] { '\"', '\n', '\r', delimiter }) != -1; if (hasSpecialChar) - return "\"" + value.Replace("\"", "\"\"") + "\""; + return "\"" + value.Replace("\"", "\"\"", StringComparison.Ordinal) + "\""; return value; } diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs index d5c3a9235151..2840fa375cf4 100644 --- a/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs +++ b/modules/mono/editor/GodotTools/GodotTools.Core/StringExtensions.cs @@ -15,7 +15,7 @@ public static string RelativeToPath(this string path, string dir) dir = Path.Combine(dir, " ").TrimEnd(); if (Path.DirectorySeparatorChar == '\\') - dir = dir.Replace("/", "\\") + "\\"; + dir = dir.Replace("/", "\\", StringComparison.Ordinal) + "\\"; var fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute); var relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute); diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs index 3cb6a6687e6e..67d55d389776 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging.CLI/ForwarderMessageHandler.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -28,7 +29,7 @@ private async Task WriteRequestToOutput(string id, MessageContent content) { await outputWriter.WriteLineAsync("======= Request ======="); await outputWriter.WriteLineAsync(id); - await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString()); + await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString(CultureInfo.InvariantCulture)); await outputWriter.WriteLineAsync(content.Body); await outputWriter.WriteLineAsync("======================="); await outputWriter.FlushAsync(); @@ -41,7 +42,7 @@ public async Task WriteResponseToOutput(string id, MessageContent content) { await outputWriter.WriteLineAsync("======= Response ======="); await outputWriter.WriteLineAsync(id); - await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString()); + await outputWriter.WriteLineAsync(content.Body.Count(c => c == '\n').ToString(CultureInfo.InvariantCulture)); await outputWriter.WriteLineAsync(content.Body); await outputWriter.WriteLineAsync("========================"); await outputWriter.FlushAsync(); diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs index ff15b96c1cf3..2944dc0d820f 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs @@ -1,5 +1,7 @@ using GodotTools.Core; +using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -92,8 +94,8 @@ public void Save() if (!isFirstProject) projectsDecl += "\n"; - projectsDecl += string.Format(_projectDeclaration, - name, projectInfo.PathRelativeToSolution.Replace("/", "\\"), projectInfo.Guid); + projectsDecl += string.Format(CultureInfo.InvariantCulture, _projectDeclaration, + name, projectInfo.PathRelativeToSolution.Replace("/", "\\", StringComparison.Ordinal), projectInfo.Guid); for (int i = 0; i < projectInfo.Configs.Count; i++) { @@ -105,15 +107,15 @@ public void Save() projPlatformsCfg += "\n"; } - slnPlatformsCfg += string.Format(_solutionPlatformsConfig, config); - projPlatformsCfg += string.Format(_projectPlatformsConfig, projectInfo.Guid, config); + slnPlatformsCfg += string.Format(CultureInfo.InvariantCulture, _solutionPlatformsConfig, config); + projPlatformsCfg += string.Format(CultureInfo.InvariantCulture, _projectPlatformsConfig, projectInfo.Guid, config); } isFirstProject = false; } string solutionPath = Path.Combine(DirectoryPath, Name + ".sln"); - string content = string.Format(_solutionTemplate, projectsDecl, slnPlatformsCfg, projPlatformsCfg); + string content = string.Format(CultureInfo.InvariantCulture, _solutionTemplate, projectsDecl, slnPlatformsCfg, projPlatformsCfg); File.WriteAllText(solutionPath, content, Encoding.UTF8); // UTF-8 with BOM } diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs index be0b7d32221f..dc9e2c592005 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs @@ -38,21 +38,18 @@ public override bool Equals([NotNullWhen(true)] object? obj) public override int GetHashCode() { - unchecked - { - int hash = 17; - hash = (hash * 29) + Solution.GetHashCode(); - hash = (hash * 29) + Project.GetHashCode(); - hash = (hash * 29) + Configuration.GetHashCode(); - hash = (hash * 29) + (RuntimeIdentifier?.GetHashCode() ?? 0); - hash = (hash * 29) + (PublishOutputDir?.GetHashCode() ?? 0); - hash = (hash * 29) + Restore.GetHashCode(); - hash = (hash * 29) + Rebuild.GetHashCode(); - hash = (hash * 29) + OnlyClean.GetHashCode(); - hash = (hash * 29) + CustomProperties.GetHashCode(); - hash = (hash * 29) + LogsDirPath.GetHashCode(); - return hash; - } + var hash = new HashCode(); + hash.Add(Solution); + hash.Add(Project); + hash.Add(Configuration); + hash.Add(RuntimeIdentifier); + hash.Add(PublishOutputDir); + hash.Add(Restore); + hash.Add(Rebuild); + hash.Add(OnlyClean); + hash.Add(CustomProperties); + hash.Add(LogsDirPath); + return hash.ToHashCode(); } // Needed for instantiation from Godot, after reloading assemblies diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs index 2071f687b38a..a0db1cdf0390 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsFilter.cs @@ -1,4 +1,5 @@ using Godot; +using System.Globalization; namespace GodotTools.Build { @@ -16,7 +17,7 @@ public int ProblemsCount set { _problemsCount = value; - ToggleButton.Text = _problemsCount.ToString(); + ToggleButton.Text = _problemsCount.ToString(CultureInfo.InvariantCulture); } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs index fef169aa07b8..b6d6d9ebf8d4 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildProblemsView.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text; @@ -83,8 +84,8 @@ private static IEnumerable ReadDiagnosticsFromFile(string csvFi "error" or _ => BuildDiagnostic.DiagnosticType.Error, }, File = csvColumns[1], - Line = int.Parse(csvColumns[2]), - Column = int.Parse(csvColumns[3]), + Line = int.Parse(csvColumns[2], CultureInfo.InvariantCulture), + Column = int.Parse(csvColumns[3], CultureInfo.InvariantCulture), Code = csvColumns[4], Message = csvColumns[5], ProjectFile = csvColumns[6], @@ -93,7 +94,7 @@ private static IEnumerable ReadDiagnosticsFromFile(string csvFi // If there's no ProjectFile but the File is a csproj, then use that. if (string.IsNullOrEmpty(diagnostic.ProjectFile) && !string.IsNullOrEmpty(diagnostic.File) && - diagnostic.File.EndsWith(".csproj")) + diagnostic.File.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase)) { diagnostic.ProjectFile = diagnostic.File; } @@ -151,9 +152,9 @@ private void CopySelectedProblems() foreach (var diagnostic in selectedDiagnostics) { if (!string.IsNullOrEmpty(diagnostic.Code)) - sb.Append($"{diagnostic.Code}: "); + sb.Append(CultureInfo.InvariantCulture, $"{diagnostic.Code}: "); - sb.AppendLine($"{diagnostic.Message} {diagnostic.File}({diagnostic.Line},{diagnostic.Column})"); + sb.AppendLine(CultureInfo.InvariantCulture, $"{diagnostic.Message} {diagnostic.File}({diagnostic.Line},{diagnostic.Column})"); } string text = sb.ToString(); @@ -251,7 +252,7 @@ private void GoToSelectedProblem() file = ProjectSettings.LocalizePath(file); - if (file.StartsWith("res://")) + if (file.StartsWith("res://", StringComparison.Ordinal)) { var script = (Script)ResourceLoader.Load(file, typeHint: Internal.CSharpLanguageType); @@ -426,7 +427,7 @@ private void UpdateProblemsTree() ? Path.GetRelativePath(projectDir, file) : "Unknown file".TTR(); - string fileItemText = string.Format("{0} ({1} issues)".TTR(), relativeFilePath, fileDiagnostics.Length); + string fileItemText = string.Format(CultureInfo.InvariantCulture, "{0} ({1} issues)".TTR(), relativeFilePath, fileDiagnostics.Length); var fileItem = _problemsTree.CreateItem(projectItem); fileItem.SetText(0, fileItemText); @@ -468,10 +469,10 @@ private ProblemItem CreateProblemItem(BuildDiagnostic diagnostic, bool includeFi shortMessage = shortMessage[..lineBreakIdx]; text.Append(shortMessage); - tooltip.Append($"Message: {diagnostic.Message}"); + tooltip.Append(CultureInfo.InvariantCulture, $"Message: {diagnostic.Message}"); if (!string.IsNullOrEmpty(diagnostic.Code)) - tooltip.Append($"\nCode: {diagnostic.Code}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nCode: {diagnostic.Code}"); string type = diagnostic.Type switch { @@ -481,7 +482,7 @@ private ProblemItem CreateProblemItem(BuildDiagnostic diagnostic, bool includeFi BuildDiagnostic.DiagnosticType.Error => "error", _ => "unknown", }; - tooltip.Append($"\nType: {type}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nType: {type}"); if (!string.IsNullOrEmpty(diagnostic.File)) { @@ -491,15 +492,15 @@ private ProblemItem CreateProblemItem(BuildDiagnostic diagnostic, bool includeFi text.Append(diagnostic.File); } - text.Append($"({diagnostic.Line},{diagnostic.Column})"); + text.Append(CultureInfo.InvariantCulture, $"({diagnostic.Line},{diagnostic.Column})"); - tooltip.Append($"\nFile: {diagnostic.File}"); - tooltip.Append($"\nLine: {diagnostic.Line}"); - tooltip.Append($"\nColumn: {diagnostic.Column}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nFile: {diagnostic.File}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nLine: {diagnostic.Line}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nColumn: {diagnostic.Column}"); } if (!string.IsNullOrEmpty(diagnostic.ProjectFile)) - tooltip.Append($"\nProject: {diagnostic.ProjectFile}"); + tooltip.Append(CultureInfo.InvariantCulture, $"\nProject: {diagnostic.ProjectFile}"); return new ProblemItem() { diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 372c4b114bf4..46020fda8959 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -12,6 +12,7 @@ using File = GodotTools.Utils.File; using OS = GodotTools.Utils.OS; using Path = System.IO.Path; +using System.Globalization; namespace GodotTools.Export { @@ -277,7 +278,7 @@ private void _ExportBeginImpl(string[] features, bool isDebug, string path, long if (platform == OS.Platforms.iOS) { // Exclude dsym folders. - return !dir.EndsWith(".dsym", StringComparison.InvariantCultureIgnoreCase); + return !dir.EndsWith(".dsym", StringComparison.OrdinalIgnoreCase); } return true; @@ -297,7 +298,7 @@ private void _ExportBeginImpl(string[] features, bool isDebug, string path, long if (platform == OS.Platforms.iOS) { // Don't recurse into dsym folders. - return !dir.EndsWith(".dsym", StringComparison.InvariantCultureIgnoreCase); + return !dir.EndsWith(".dsym", StringComparison.OrdinalIgnoreCase); } return true; @@ -313,13 +314,13 @@ private void _ExportBeginImpl(string[] features, bool isDebug, string path, long byte[] fileData = File.ReadAllBytes(path); string hash = Convert.ToBase64String(SHA512.HashData(fileData)); - manifest.Append($"{filePath}\t{hash}\n"); + manifest.Append(CultureInfo.InvariantCulture, $"{filePath}\t{hash}\n"); AddFile($"res://.godot/mono/publish/{arch}/{filePath}", fileData, false); } else { - if (platform == OS.Platforms.iOS && path.EndsWith(".dat")) + if (platform == OS.Platforms.iOS && path.EndsWith(".dat", StringComparison.OrdinalIgnoreCase)) { AddIosBundleFile(path); } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index dcbcc4352b56..ef9437066e81 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -4,6 +4,7 @@ using GodotTools.Utils; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using GodotTools.Build; @@ -202,10 +203,10 @@ public Error OpenInExternalEditor(Script script, int line, int col) var insideQuotes = false; var hasFileFlag = false; - execArgs = execArgs.ReplaceN("{line}", line.ToString()); - execArgs = execArgs.ReplaceN("{col}", col.ToString()); + execArgs = execArgs.ReplaceN("{line}", line.ToString(CultureInfo.InvariantCulture)); + execArgs = execArgs.ReplaceN("{col}", col.ToString(CultureInfo.InvariantCulture)); execArgs = execArgs.StripEdges(true, true); - execArgs = execArgs.Replace("\\\\", "\\"); + execArgs = execArgs.Replace("\\\\", "\\", StringComparison.Ordinal); for (int i = 0; i < execArgs.Length; ++i) { @@ -225,7 +226,7 @@ public Error OpenInExternalEditor(Script script, int line, int col) } var arg = execArgs.Substr(from, numChars); - if (arg.Contains("{file}")) + if (arg.Contains("{file}", StringComparison.OrdinalIgnoreCase)) { hasFileFlag = true; } diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs index 94499c4f380b..3b761577ae8f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/GodotSharpDirs.cs @@ -73,7 +73,7 @@ public static void DetermineProjectLocation() string? slnParentDir = (string?)ProjectSettings.GetSetting("dotnet/project/solution_directory"); if (string.IsNullOrEmpty(slnParentDir)) slnParentDir = "res://"; - else if (!slnParentDir.StartsWith("res://")) + else if (!slnParentDir.StartsWith("res://", System.StringComparison.Ordinal)) slnParentDir = "res://" + slnParentDir; // The csproj should be in the same folder as project.godot. diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index d5d8de93d2f2..355264e4b3b2 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -274,7 +274,7 @@ private static void AppendProcessFileNameForDisplay(this StringBuilder builder, if (builder.Length > 0) builder.Append(' '); - if (fileName.Contains(' ')) + if (fileName.Contains(' ', StringComparison.Ordinal)) { builder.Append('"'); builder.Append(fileName); @@ -297,7 +297,7 @@ private static void AppendProcessArgumentsForDisplay(this StringBuilder builder, if (builder.Length > 0) builder.Append(' '); - if (argument.Contains(' ')) + if (argument.Contains(' ', StringComparison.Ordinal)) { builder.Append('"'); builder.Append(argument); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 772209064cff..c29a0f2bd883 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.InteropServices; using Godot.NativeInterop; @@ -776,11 +777,11 @@ private static Color Named(string name, Color @default) private static bool FindNamedColor(string name, out Color color) { - name = name.Replace(" ", string.Empty); - name = name.Replace("-", string.Empty); - name = name.Replace("_", string.Empty); - name = name.Replace("'", string.Empty); - name = name.Replace(".", string.Empty); + name = name.Replace(" ", string.Empty, StringComparison.Ordinal); + name = name.Replace("-", string.Empty, StringComparison.Ordinal); + name = name.Replace("_", string.Empty, StringComparison.Ordinal); + name = name.Replace("'", string.Empty, StringComparison.Ordinal); + name = name.Replace(".", string.Empty, StringComparison.Ordinal); name = name.ToUpperInvariant(); return Colors.namedColors.TryGetValue(name, out color); @@ -1329,7 +1330,9 @@ public override readonly string ToString() /// A string representation of this color. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({R.ToString(format)}, {G.ToString(format)}, {B.ToString(format)}, {A.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs index ab2e0a78b9ab..fc6e7a3ebe00 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; @@ -698,7 +699,7 @@ public static godot_variant ConvertToVariant(object? obj) case GodotObject godotObject: return VariantUtils.CreateFrom(godotObject); case Enum @enum: - return VariantUtils.CreateFrom(Convert.ToInt64(@enum)); + return VariantUtils.CreateFrom(Convert.ToInt64(@enum, CultureInfo.InvariantCulture)); case Collections.IGenericGodotDictionary godotDictionary: return VariantUtils.CreateFrom(godotDictionary.UnderlyingDictionary); case Collections.IGenericGodotArray godotArray: @@ -777,7 +778,7 @@ private static readonly System.Collections.Generic.Dictionary(variant), type); + return Convert.ChangeType(VariantUtils.ConvertTo(variant), type, CultureInfo.InvariantCulture); if (typeof(GodotObject[]).IsAssignableFrom(type)) { @@ -796,7 +797,7 @@ static GodotObject[] ConvertToSystemArrayOfGodotObject(in godot_array nativeArra } using var godotArray = NativeFuncs.godotsharp_variant_as_array(variant); - return Convert.ChangeType(ConvertToSystemArrayOfGodotObject(godotArray, type), type); + return Convert.ChangeType(ConvertToSystemArrayOfGodotObject(godotArray, type), type, CultureInfo.InvariantCulture); } if (type.IsEnum) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs index a7640043cef7..8195828de94f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.exceptions.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.Text; #nullable enable @@ -73,7 +74,7 @@ public override string Message if (!string.IsNullOrEmpty(_nativeClassName)) { - sb.Append($" (Method '{_nativeClassName}')"); + sb.Append(CultureInfo.InvariantCulture, $" (Method '{_nativeClassName}')"); } return sb.ToString(); @@ -131,7 +132,7 @@ public override string Message if (!string.IsNullOrEmpty(_nativeMethodName)) { - sb.Append($" (Method '{_nativeMethodName}')"); + sb.Append(CultureInfo.InvariantCulture, $" (Method '{_nativeMethodName}')"); } return sb.ToString(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index f5dc34d824e9..c5998eca5c08 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -435,7 +435,9 @@ public override readonly string ToString() /// A string representation of this plane. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"{_normal.ToString(format)}, {_d.ToString(format)}"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs index a646caad3e9d..2aac23d79969 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -1023,10 +1023,12 @@ public override readonly string ToString() /// A string representation of this projection. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"{X.X.ToString(format)}, {X.Y.ToString(format)}, {X.Z.ToString(format)}, {X.W.ToString(format)}\n" + $"{Y.X.ToString(format)}, {Y.Y.ToString(format)}, {Y.Z.ToString(format)}, {Y.W.ToString(format)}\n" + $"{Z.X.ToString(format)}, {Z.Y.ToString(format)}, {Z.Z.ToString(format)}, {Z.W.ToString(format)}\n" + $"{W.X.ToString(format)}, {W.Y.ToString(format)}, {W.Z.ToString(format)}, {W.W.ToString(format)}\n"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index 2344e8c5104b..6a8cb1ba042a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -822,7 +822,9 @@ public override readonly string ToString() /// A string representation of this quaternion. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)}, {W.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index e89bbbd37085..f249bac69c56 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -106,7 +106,7 @@ public static int BinToInt(this string instance) instance = instance.Substring(1); } - if (instance.StartsWith("0b")) + if (instance.StartsWith("0b", StringComparison.OrdinalIgnoreCase)) { instance = instance.Substring(2); } @@ -314,7 +314,7 @@ public static string CUnescape(this string instance) /// The capitalized string. public static string Capitalize(this string instance) { - string aux = instance.CamelcaseToUnderscore(true).Replace("_", " ").Trim(); + string aux = instance.CamelcaseToUnderscore(true).Replace("_", " ", StringComparison.Ordinal).Trim(); string cap = string.Empty; for (int i = 0; i < aux.GetSliceCount(" "); i++) @@ -742,7 +742,7 @@ public static byte[] HexDecode(this string instance) byte[] ret = new byte[len]; for (int i = 0; i < len; i++) { - ret[i] = (byte)int.Parse(instance.AsSpan(i * 2, 2), NumberStyles.AllowHexSpecifier); + ret[i] = (byte)int.Parse(instance.AsSpan(i * 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture); } return ret; } @@ -816,12 +816,12 @@ public static int HexToInt(this string instance) instance = instance.Substring(1); } - if (instance.StartsWith("0x")) + if (instance.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { instance = instance.Substring(2); } - return sign * int.Parse(instance, NumberStyles.HexNumber); + return sign * int.Parse(instance, NumberStyles.HexNumber, CultureInfo.InvariantCulture); } /// @@ -878,7 +878,7 @@ public static bool IsAbsolutePath(this string instance) if (string.IsNullOrEmpty(instance)) return false; else if (instance.Length > 1) - return instance[0] == '/' || instance[0] == '\\' || instance.Contains(":/") || instance.Contains(":\\"); + return instance[0] == '/' || instance[0] == '\\' || instance.Contains(":/", StringComparison.Ordinal) || instance.Contains(":\\", StringComparison.Ordinal); else return instance[0] == '/' || instance[0] == '\\'; } @@ -1120,7 +1120,7 @@ public static bool IsValidInt(this string instance) /// If the string contains a valid IP address. public static bool IsValidIPAddress(this string instance) { - if (instance.Contains(':')) + if (instance.Contains(':', StringComparison.Ordinal)) { string[] ip = instance.Split(':'); @@ -1404,23 +1404,10 @@ public static string PathJoin(this string instance, string file) return instance + "/" + file; } - /// - /// Replace occurrences of a substring for different ones inside the string. - /// - /// - /// The string to modify. - /// The substring to be replaced in the string. - /// The substring that replaces . - /// The string with the substring occurrences replaced. - public static string Replace(this string instance, string what, string forwhat) - { - return instance.Replace(what, forwhat); - } - /// /// Replace occurrences of a substring for different ones inside the string, but search case-insensitive. /// - /// + /// /// The string to modify. /// The substring to be replaced in the string. /// The substring that replaces . @@ -1634,7 +1621,7 @@ public static float[] SplitFloats(this string instance, string divisor, bool all if (end < 0) end = len; if (allowEmpty || end > from) - ret.Add(float.Parse(instance.Substring(from))); + ret.Add(float.Parse(instance.Substring(from), CultureInfo.InvariantCulture)); if (end == len) break; @@ -1738,7 +1725,7 @@ public static byte[] ToAsciiBuffer(this string instance) /// The number representation of the string. public static float ToFloat(this string instance) { - return float.Parse(instance); + return float.Parse(instance, CultureInfo.InvariantCulture); } /// @@ -1749,7 +1736,7 @@ public static float ToFloat(this string instance) /// The number representation of the string. public static int ToInt(this string instance) { - return int.Parse(instance); + return int.Parse(instance, CultureInfo.InvariantCulture); } /// @@ -1802,7 +1789,7 @@ public static byte[] ToUtf8Buffer(this string instance) /// A copy of the string with the prefix string removed from the start. public static string TrimPrefix(this string instance, string prefix) { - if (instance.StartsWith(prefix)) + if (instance.StartsWith(prefix, StringComparison.Ordinal)) return instance.Substring(prefix.Length); return instance; @@ -1816,7 +1803,7 @@ public static string TrimPrefix(this string instance, string prefix) /// A copy of the string with the suffix string removed from the end. public static string TrimSuffix(this string instance, string suffix) { - if (instance.EndsWith(suffix)) + if (instance.EndsWith(suffix, StringComparison.Ordinal)) return instance.Substring(0, instance.Length - suffix.Length); return instance; @@ -1833,7 +1820,7 @@ public static string TrimSuffix(this string instance, string suffix) /// The unescaped string. public static string URIDecode(this string instance) { - return Uri.UnescapeDataString(instance.Replace("+", "%20")); + return Uri.UnescapeDataString(instance.Replace("+", "%20", StringComparison.Ordinal)); } /// @@ -1860,10 +1847,10 @@ public static string URIEncode(this string instance) /// The string sanitized as a valid node name. public static string ValidateNodeName(this string instance) { - string name = instance.Replace(_invalidNodeNameCharacters[0], ""); + string name = instance.Replace(_invalidNodeNameCharacters[0], "", StringComparison.Ordinal); for (int i = 1; i < _invalidNodeNameCharacters.Length; i++) { - name = name.Replace(_invalidNodeNameCharacters[i], ""); + name = name.Replace(_invalidNodeNameCharacters[i], "", StringComparison.Ordinal); } return name; } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index a27a1ab1cf9d..bd92e48bceae 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -1021,7 +1021,9 @@ public override readonly string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs index 8960323754a9..1a386d9da1fd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2I.cs @@ -600,7 +600,9 @@ public override readonly string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 54d698345f41..6e77512fc86a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -1123,7 +1123,9 @@ public override readonly string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs index 2d7bbc926dbd..d0ad1922f611 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3I.cs @@ -655,7 +655,9 @@ public override readonly string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs index 87c01ad5ea66..115e65bbdb04 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -905,7 +905,9 @@ public override string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)}, {W.ToString(format)})"; +#pragma warning restore CA1305 } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs index 9a85f359d7e1..527c8e5022cc 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4I.cs @@ -676,7 +676,9 @@ public override readonly string ToString() /// A string representation of this vector. public readonly string ToString(string? format) { - return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)}), {W.ToString(format)})"; +#pragma warning disable CA1305 // Disable warning: "Specify IFormatProvider" + return $"({X.ToString(format)}, {Y.ToString(format)}, {Z.ToString(format)}, {W.ToString(format)})"; +#pragma warning restore CA1305 } } }