Skip to content

Commit

Permalink
Merge pull request #87133 from Repiteo/dotnet/enforce-globalization-r…
Browse files Browse the repository at this point in the history
…ules

C#: Enforce globalization code quality rules
  • Loading branch information
akien-mga authored Feb 20, 2024
2 parents 73d502f + 000d12d commit 1aab6e9
Show file tree
Hide file tree
Showing 25 changed files with 103 additions and 98 deletions.
9 changes: 0 additions & 9 deletions modules/mono/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
Expand Down Expand Up @@ -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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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++)
{
Expand All @@ -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
}
Expand Down
27 changes: 12 additions & 15 deletions modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Godot;
using System.Globalization;

namespace GodotTools.Build
{
Expand All @@ -16,7 +17,7 @@ public int ProblemsCount
set
{
_problemsCount = value;
ToggleButton.Text = _problemsCount.ToString();
ToggleButton.Text = _problemsCount.ToString(CultureInfo.InvariantCulture);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -83,8 +84,8 @@ private static IEnumerable<BuildDiagnostic> 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],
Expand All @@ -93,7 +94,7 @@ private static IEnumerable<BuildDiagnostic> 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;
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
{
Expand All @@ -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))
{
Expand All @@ -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()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down
9 changes: 5 additions & 4 deletions modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
13 changes: 8 additions & 5 deletions modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
using Godot.NativeInterop;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1329,7 +1330,9 @@ public override readonly string ToString()
/// <returns>A string representation of this color.</returns>
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
}
}
}
Loading

0 comments on commit 1aab6e9

Please sign in to comment.