Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C#: Enforce globalization code quality rules #87133

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
raulsntos marked this conversation as resolved.
Show resolved Hide resolved
# 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
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
Loading