diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/TaskHelper.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/TaskHelper.cs
index 26f9a851a..6bd3b87dd 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/TaskHelper.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/Helpers/TaskHelper.cs
@@ -13,6 +13,8 @@ namespace StyleCop.Analyzers.Helpers
internal static class TaskHelper
{
+ public static readonly Task CompletedTask = Task.FromResult(0);
+
public static bool IsTaskReturningMethod(SemanticModel semanticModel, MethodDeclarationSyntax methodDeclarationSyntax, CancellationToken cancellationToken)
{
return IsTaskType(semanticModel, methodDeclarationSyntax.ReturnType, cancellationToken);
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/NamingRules/SA1317CodeFixProvider.cs b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/NamingRules/SA1317CodeFixProvider.cs
new file mode 100644
index 000000000..5b5780437
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/NamingRules/SA1317CodeFixProvider.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.NamingRules
+{
+ using System.Collections.Immutable;
+ using System.Composition;
+ using System.Threading.Tasks;
+ using Microsoft.CodeAnalysis;
+ using Microsoft.CodeAnalysis.CodeActions;
+ using Microsoft.CodeAnalysis.CodeFixes;
+ using Microsoft.CodeAnalysis.CSharp;
+ using StyleCop.Analyzers.Helpers;
+
+ ///
+ /// Implements a code fix for .
+ ///
+ ///
+ /// To fix a violation of this rule, replace non-Latin letters with appropriate Latin letters.
+ ///
+ [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(SA1317CodeFixProvider))]
+ [Shared]
+ internal class SA1317CodeFixProvider : CodeFixProvider
+ {
+ ///
+ public override ImmutableArray FixableDiagnosticIds { get; } =
+ ImmutableArray.Create(SA1317IdentifierShouldBeNamedOnlyWithLatinLetters.DiagnosticId);
+
+ ///
+ public override FixAllProvider GetFixAllProvider()
+ {
+ return null;
+ }
+
+ ///
+ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ await TaskHelper.CompletedTask.ConfigureAwait(false);
+ }
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/NamingRules/SA1317CSharp10UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/NamingRules/SA1317CSharp10UnitTests.cs
new file mode 100644
index 000000000..ed6960bcd
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp10/NamingRules/SA1317CSharp10UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp10.NamingRules
+{
+ using StyleCop.Analyzers.Test.CSharp9.NamingRules;
+
+ public partial class SA1317CSharp10UnitTests : SA1317CSharp9UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/NamingRules/SA1317CSharp11UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/NamingRules/SA1317CSharp11UnitTests.cs
new file mode 100644
index 000000000..b4671e508
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp11/NamingRules/SA1317CSharp11UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp11.NamingRules
+{
+ using StyleCop.Analyzers.Test.CSharp10.NamingRules;
+
+ public partial class SA1317CSharp11UnitTests : SA1317CSharp10UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/NamingRules/SA1317CSharp12UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/NamingRules/SA1317CSharp12UnitTests.cs
new file mode 100644
index 000000000..9e8f09f80
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/NamingRules/SA1317CSharp12UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp12.NamingRules
+{
+ using StyleCop.Analyzers.Test.CSharp11.NamingRules;
+
+ public partial class SA1317CSharp12UnitTests : SA1317CSharp11UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp13/NamingRules/SA1317CSharp13UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp13/NamingRules/SA1317CSharp13UnitTests.cs
new file mode 100644
index 000000000..c352df66a
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp13/NamingRules/SA1317CSharp13UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp13.NamingRules
+{
+ using StyleCop.Analyzers.Test.CSharp12.NamingRules;
+
+ public partial class SA1317CSharp13UnitTests : SA1317CSharp12UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/NamingRules/SA1317CSharp7UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/NamingRules/SA1317CSharp7UnitTests.cs
new file mode 100644
index 000000000..ad94a4894
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/NamingRules/SA1317CSharp7UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp7.NamingRules
+{
+ using StyleCop.Analyzers.Test.NamingRules;
+
+ public partial class SA1317CSharp7UnitTests : SA1317UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1317CSharp8UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1317CSharp8UnitTests.cs
new file mode 100644
index 000000000..a8ac93634
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/NamingRules/SA1317CSharp8UnitTests.cs
@@ -0,0 +1,13 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp8.NamingRules
+{
+ using StyleCop.Analyzers.Test.CSharp7.NamingRules;
+
+ public partial class SA1317CSharp8UnitTests : SA1317CSharp7UnitTests
+ {
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1317CSharp9UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1317CSharp9UnitTests.cs
new file mode 100644
index 000000000..1ac8e9fc7
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/NamingRules/SA1317CSharp9UnitTests.cs
@@ -0,0 +1,46 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.CSharp9.NamingRules
+{
+ using System;
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Microsoft.CodeAnalysis.Testing;
+ using StyleCop.Analyzers.Test.CSharp8.NamingRules;
+ using Xunit;
+ using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
+ StyleCop.Analyzers.NamingRules.SA1317IdentifierShouldBeNamedOnlyWithLatinLetters,
+ StyleCop.Analyzers.NamingRules.SA1317CodeFixProvider>;
+
+ public partial class SA1317CSharp9UnitTests : SA1317CSharp8UnitTests
+ {
+ [Fact]
+ public async Task TestRecordNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public record RecordName {}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestRecordNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public record RеcоrdNаmе {}";
+
+ Console.WriteLine("Test");
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("RеcоrdNаmе", 1).WithLocation(1, 15),
+ Diagnostic().WithArguments("RеcоrdNаmе", 3).WithLocation(1, 15),
+ Diagnostic().WithArguments("RеcоrdNаmе", 7).WithLocation(1, 15),
+ Diagnostic().WithArguments("RеcоrdNаmе", 9).WithLocation(1, 15),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1317UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1317UnitTests.cs
new file mode 100644
index 000000000..992408925
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/NamingRules/SA1317UnitTests.cs
@@ -0,0 +1,495 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.Test.NamingRules
+{
+ using System.Threading;
+ using System.Threading.Tasks;
+ using Microsoft.CodeAnalysis.Testing;
+ using Xunit;
+ using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
+ StyleCop.Analyzers.NamingRules.SA1317IdentifierShouldBeNamedOnlyWithLatinLetters,
+ StyleCop.Analyzers.NamingRules.SA1317CodeFixProvider>;
+
+ public class SA1317UnitTests
+ {
+ [Fact]
+ public async Task TestClassNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName {}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestClassNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class СlаssNаmе {}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("СlаssNаmе", 0).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 2).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 6).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 8).WithLocation(1, 14),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestMethodNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName() {}
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestMethodNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MеthоdNаmе() {}
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("MеthоdNаmе", 1).WithLocation(3, 17),
+ Diagnostic().WithArguments("MеthоdNаmе", 4).WithLocation(3, 17),
+ Diagnostic().WithArguments("MеthоdNаmе", 7).WithLocation(3, 17),
+ Diagnostic().WithArguments("MеthоdNаmе", 9).WithLocation(3, 17),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestConstructorNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public ClassName() {}
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestConstructorNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class СlаssNаmе
+{
+ public СlаssNаmе() {}
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("СlаssNаmе", 0).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 2).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 6).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 8).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 0).WithLocation(3, 12),
+ Diagnostic().WithArguments("СlаssNаmе", 2).WithLocation(3, 12),
+ Diagnostic().WithArguments("СlаssNаmе", 6).WithLocation(3, 12),
+ Diagnostic().WithArguments("СlаssNаmе", 8).WithLocation(3, 12),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestDestructorNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ ~ClassName() {}
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestDestructorNameContainsInvalidCharactersAsync()
+ {
+ var testCode = @"public class СlаssNаmе
+{
+ ~СlаssNаmе() {}
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("СlаssNаmе", 0).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 2).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 6).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 8).WithLocation(1, 14),
+ Diagnostic().WithArguments("СlаssNаmе", 0).WithLocation(3, 6),
+ Diagnostic().WithArguments("СlаssNаmе", 2).WithLocation(3, 6),
+ Diagnostic().WithArguments("СlаssNаmе", 6).WithLocation(3, 6),
+ Diagnostic().WithArguments("СlаssNаmе", 8).WithLocation(3, 6),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEnumNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"enum EnumName {}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEnumNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"enum ЕnumNаmе {}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("ЕnumNаmе", 0).WithLocation(1, 6),
+ Diagnostic().WithArguments("ЕnumNаmе", 5).WithLocation(1, 6),
+ Diagnostic().WithArguments("ЕnumNаmе", 7).WithLocation(1, 6),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEnumValueNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"enum EnumName
+{
+ EnumValueName
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEnumValueNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"enum EnumName
+{
+ ЕnumVаluеNаmе
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("ЕnumVаluеNаmе", 0).WithLocation(3, 5),
+ Diagnostic().WithArguments("ЕnumVаluеNаmе", 5).WithLocation(3, 5),
+ Diagnostic().WithArguments("ЕnumVаluеNаmе", 8).WithLocation(3, 5),
+ Diagnostic().WithArguments("ЕnumVаluеNаmе", 10).WithLocation(3, 5),
+ Diagnostic().WithArguments("ЕnumVаluеNаmе", 12).WithLocation(3, 5),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestStructNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public struct StructName {}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestStructNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public struct StruсtNаmе {}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("StruсtNаmе", 4).WithLocation(1, 15),
+ Diagnostic().WithArguments("StruсtNаmе", 7).WithLocation(1, 15),
+ Diagnostic().WithArguments("StruсtNаmе", 9).WithLocation(1, 15),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestInterfaceNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"interface InterfaceName {}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestInterfaceNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"interface IntеrfасеNаmе {}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("IntеrfасеNаmе", 3).WithLocation(1, 11),
+ Diagnostic().WithArguments("IntеrfасеNаmе", 6).WithLocation(1, 11),
+ Diagnostic().WithArguments("IntеrfасеNаmе", 7).WithLocation(1, 11),
+ Diagnostic().WithArguments("IntеrfасеNаmе", 8).WithLocation(1, 11),
+ Diagnostic().WithArguments("IntеrfасеNаmе", 10).WithLocation(1, 11),
+ Diagnostic().WithArguments("IntеrfасеNаmе", 12).WithLocation(1, 11),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestPropertyNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public int PropertyName { get; set; }
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestPropertyNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public int РrореrtуNаmе { get; set; }
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("РrореrtуNаmе", 0).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 2).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 3).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 4).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 7).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 9).WithLocation(3, 16),
+ Diagnostic().WithArguments("РrореrtуNаmе", 11).WithLocation(3, 16),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestFieldNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public int FirstFieldName, SecondFieldName;
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestFieldNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public int FirstFiеldNаmе, SесоndFiеldNаmе;
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("FirstFiеldNаmе", 7).WithLocation(3, 16),
+ Diagnostic().WithArguments("FirstFiеldNаmе", 11).WithLocation(3, 16),
+ Diagnostic().WithArguments("FirstFiеldNаmе", 13).WithLocation(3, 16),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 1).WithLocation(3, 32),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 2).WithLocation(3, 32),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 3).WithLocation(3, 32),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 8).WithLocation(3, 32),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 12).WithLocation(3, 32),
+ Diagnostic().WithArguments("SесоndFiеldNаmе", 14).WithLocation(3, 32),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEventNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public delegate void DelegateName();
+ public event DelegateName EventName;
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestEventNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public delegate void DelegateName();
+ public event DelegateName ЕvеntNаmе;
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("ЕvеntNаmе", 0).WithLocation(4, 31),
+ Diagnostic().WithArguments("ЕvеntNаmе", 2).WithLocation(4, 31),
+ Diagnostic().WithArguments("ЕvеntNаmе", 6).WithLocation(4, 31),
+ Diagnostic().WithArguments("ЕvеntNаmе", 8).WithLocation(4, 31),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestDelegateNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public delegate void DelegateName();
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestDelegateNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public delegate void DеlеgаtеNаmе();
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 1).WithLocation(3, 26),
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 3).WithLocation(3, 26),
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 5).WithLocation(3, 26),
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 7).WithLocation(3, 26),
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 9).WithLocation(3, 26),
+ Diagnostic().WithArguments("DеlеgаtеNаmе", 11).WithLocation(3, 26),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestVariableNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName()
+ {
+ int variableName1, variableName2 = 0;
+
+ for (var variableName3 = 0; variableName3 < 10; ++variableName3) {}
+ }
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestVariableNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName()
+ {
+ int vаriаblеNаmе1, vаriаblеNаmе2 = 0;
+
+ for (var vаriаblеNаmе3 = 0; vаriаblеNаmе3 < 10; ++vаriаblеNаmе3) {}
+ }
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("vаriаblеNаmе1", 1).WithLocation(5, 13),
+ Diagnostic().WithArguments("vаriаblеNаmе1", 4).WithLocation(5, 13),
+ Diagnostic().WithArguments("vаriаblеNаmе1", 7).WithLocation(5, 13),
+ Diagnostic().WithArguments("vаriаblеNаmе1", 9).WithLocation(5, 13),
+ Diagnostic().WithArguments("vаriаblеNаmе1", 11).WithLocation(5, 13),
+ Diagnostic().WithArguments("vаriаblеNаmе2", 1).WithLocation(5, 28),
+ Diagnostic().WithArguments("vаriаblеNаmе2", 4).WithLocation(5, 28),
+ Diagnostic().WithArguments("vаriаblеNаmе2", 7).WithLocation(5, 28),
+ Diagnostic().WithArguments("vаriаblеNаmе2", 9).WithLocation(5, 28),
+ Diagnostic().WithArguments("vаriаblеNаmе2", 11).WithLocation(5, 28),
+ Diagnostic().WithArguments("vаriаblеNаmе3", 1).WithLocation(7, 18),
+ Diagnostic().WithArguments("vаriаblеNаmе3", 4).WithLocation(7, 18),
+ Diagnostic().WithArguments("vаriаblеNаmе3", 7).WithLocation(7, 18),
+ Diagnostic().WithArguments("vаriаblеNаmе3", 9).WithLocation(7, 18),
+ Diagnostic().WithArguments("vаriаblеNаmе3", 11).WithLocation(7, 18),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestConstantNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName()
+ {
+ const int constName1 = 0;
+ }
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestConstantNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName()
+ {
+ const int соnstNаmе1 = 0;
+ }
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("соnstNаmе1", 0).WithLocation(5, 19),
+ Diagnostic().WithArguments("соnstNаmе1", 1).WithLocation(5, 19),
+ Diagnostic().WithArguments("соnstNаmе1", 6).WithLocation(5, 19),
+ Diagnostic().WithArguments("соnstNаmе1", 8).WithLocation(5, 19),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestParameterNameDoesNotContainNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName(int parameterName) {}
+}";
+
+ await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ [Fact]
+ public async Task TestParameterNameContainsNonLatinLettersAsync()
+ {
+ var testCode = @"public class ClassName
+{
+ public void MethodName(int раrаmеtеrNаmе) {}
+}";
+
+ var expected = new DiagnosticResult[]
+ {
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 0).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 1).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 3).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 5).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 7).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 10).WithLocation(3, 32),
+ Diagnostic().WithArguments("раrаmеtеrNаmе", 12).WithLocation(3, 32),
+ };
+
+ await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerReleases.Unshipped.md b/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerReleases.Unshipped.md
index 83e85e73d..146f3e8ca 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerReleases.Unshipped.md
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/AnalyzerReleases.Unshipped.md
@@ -8,6 +8,7 @@ Rule ID | Category | Severity | Notes
SA1141 | StyleCop.CSharp.ReadabilityRules | Warning | SA1141UseTupleSyntax, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1141.md)
SA1142 | StyleCop.CSharp.ReadabilityRules | Warning | SA1142ReferToTupleElementsByName, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1142.md)
SA1316 | StyleCop.CSharp.NamingRules | Warning | SA1316TupleElementNamesShouldUseCorrectCasing, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1316.md)
+SA1317 | StyleCop.CSharp.NamingRules | Warning | SA1317IdentifierShouldBeNamedOnlyWithLatinLetters, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1317.md)
SA1414 | StyleCop.CSharp.ReadabilityRules | Warning | SA1414TupleTypesInSignaturesShouldHaveElementNames, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1414.md)
SA1518 | StyleCop.CSharp.LayoutRules | Warning | SA1518UseLineEndingsCorrectlyAtEndOfFile, [Documentation](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1518.md)
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/Lightup/.generated/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp.CSharpResxGenerator/NamingResources.Designer.cs b/StyleCop.Analyzers/StyleCop.Analyzers/Lightup/.generated/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp.CSharpResxGenerator/NamingResources.Designer.cs
index 6393d2d1b..4acdba9ec 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/Lightup/.generated/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp.CSharpResxGenerator/NamingResources.Designer.cs
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/Lightup/.generated/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp/Microsoft.CodeAnalysis.ResxSourceGenerator.CSharp.CSharpResxGenerator/NamingResources.Designer.cs
@@ -118,6 +118,12 @@ internal static partial class NamingResources
public static string @SA1316MessageFormat => GetResourceString("SA1316MessageFormat")!;
/// Tuple element names should use correct casing
public static string @SA1316Title => GetResourceString("SA1316Title")!;
+ /// An identifier should be named only with Latin letters.
+ public static string @SA1317Description => GetResourceString("SA1317Description")!;
+ /// Identifier '{0}' should be named only with Latin letters. Position {1}.
+ public static string @SA1317MessageFormat => GetResourceString("SA1317MessageFormat")!;
+ /// Identifier should be named only with Latin letters
+ public static string @SA1317Title => GetResourceString("SA1317Title")!;
/// A field name in C# does not begin with an underscore.
public static string @SX1309Description => GetResourceString("SX1309Description")!;
/// Field '{0}' should begin with an underscore
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/NamingResources.resx b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/NamingResources.resx
index 80a01e537..ed0e8c9d0 100644
--- a/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/NamingResources.resx
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/NamingResources.resx
@@ -273,6 +273,15 @@
Tuple element names should use correct casing
+
+ An identifier should be named only with Latin letters.
+
+
+ Identifier '{0}' should be named only with Latin letters. Position {1}.
+
+
+ Identifier should be named only with Latin letters
+
A field name in C# does not begin with an underscore.
diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1317IdentifierShouldBeNamedOnlyWithLatinLetters.cs b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1317IdentifierShouldBeNamedOnlyWithLatinLetters.cs
new file mode 100644
index 000000000..13b3bcba7
--- /dev/null
+++ b/StyleCop.Analyzers/StyleCop.Analyzers/NamingRules/SA1317IdentifierShouldBeNamedOnlyWithLatinLetters.cs
@@ -0,0 +1,185 @@
+// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
+// Licensed under the MIT License. See LICENSE in the project root for license information.
+
+#nullable disable
+
+namespace StyleCop.Analyzers.NamingRules
+{
+ using System;
+ using System.Collections.Immutable;
+ using Microsoft.CodeAnalysis;
+ using Microsoft.CodeAnalysis.CSharp;
+ using Microsoft.CodeAnalysis.CSharp.Syntax;
+ using Microsoft.CodeAnalysis.Diagnostics;
+ using StyleCop.Analyzers.Lightup;
+ using StyleCop.Analyzers.Settings.ObjectModel;
+
+ ///
+ /// An identifier name contains non-Latin letters.
+ ///
+ ///
+ /// A violation of this rule occurs when an identifier name contains non-Latin letters.
+ /// This is very common mistake to use Cyrillic letter instead of the Latin letter in some countries that use Cyrillic alphabet
+ /// (Bulgaria, Russia, Serbia, Macedonia, Ukraine, etc.).
+ /// For example, these letters ('a' ('а'), 'o' ('о'), 'e' ('е'), 'k' ('к') and few others) look the same in both Latin and Cyrillic alphabets.
+ ///
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ internal class SA1317IdentifierShouldBeNamedOnlyWithLatinLetters : DiagnosticAnalyzer
+ {
+ ///
+ /// The ID for diagnostics produced by the analyzer.
+ ///
+ public const string DiagnosticId = "SA1317";
+ private const string HelpLink = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1317.md";
+ private static readonly LocalizableString Title = new LocalizableResourceString(nameof(NamingResources.SA1317Title), NamingResources.ResourceManager, typeof(NamingResources));
+ private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(NamingResources.SA1317MessageFormat), NamingResources.ResourceManager, typeof(NamingResources));
+ private static readonly LocalizableString Description = new LocalizableResourceString(nameof(NamingResources.SA1317Description), NamingResources.ResourceManager, typeof(NamingResources));
+
+ private static readonly DiagnosticDescriptor Descriptor =
+ new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.NamingRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
+
+ private static readonly Action HandleMemberDeclarationIdentifierNameAction = HandleMemberDeclarationIdentifierName;
+ private static readonly Action HandleVariableDeclarationIdentifierNameAction = HandleVariableDeclarationIdentifierName;
+ private static readonly Action HandleParameterIdentifierNameAction = HandleParameterIdentifierName;
+
+ private static readonly ImmutableArray MemberDeclarationKinds =
+ ImmutableArray.Create(
+ SyntaxKind.EventFieldDeclaration,
+ SyntaxKind.EventDeclaration,
+ SyntaxKind.FieldDeclaration,
+ SyntaxKind.ConstructorDeclaration,
+ SyntaxKind.DestructorDeclaration,
+ SyntaxKind.MethodDeclaration,
+ SyntaxKind.NamespaceDeclaration,
+ SyntaxKind.PropertyDeclaration,
+ SyntaxKind.EnumDeclaration,
+ SyntaxKind.EnumMemberDeclaration,
+ SyntaxKind.StructDeclaration,
+ SyntaxKind.InterfaceDeclaration,
+ SyntaxKind.DelegateDeclaration,
+ SyntaxKind.ClassDeclaration,
+ SyntaxKindEx.RecordDeclaration);
+
+ ///
+ public override ImmutableArray SupportedDiagnostics { get; } =
+ ImmutableArray.Create(Descriptor);
+
+ ///
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+
+ context.RegisterCompilationStartAction(context =>
+ {
+ context.RegisterSyntaxNodeAction(HandleMemberDeclarationIdentifierNameAction, MemberDeclarationKinds);
+ context.RegisterSyntaxNodeAction(HandleVariableDeclarationIdentifierNameAction, SyntaxKind.VariableDeclaration);
+ context.RegisterSyntaxNodeAction(HandleParameterIdentifierNameAction, SyntaxKind.Parameter);
+ });
+ }
+
+ private static void HandleMemberDeclarationIdentifierName(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
+ {
+ var syntax = (MemberDeclarationSyntax)context.Node;
+
+ if (syntax is MethodDeclarationSyntax methodDeclaration)
+ {
+ CheckIdentifierName(context, methodDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is ConstructorDeclarationSyntax constructorDeclaration)
+ {
+ CheckIdentifierName(context, constructorDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is DestructorDeclarationSyntax destructorDeclaration)
+ {
+ CheckIdentifierName(context, destructorDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is BaseTypeDeclarationSyntax typeDeclaration)
+ {
+ CheckIdentifierName(context, typeDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is PropertyDeclarationSyntax propertyDeclaration)
+ {
+ CheckIdentifierName(context, propertyDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is DelegateDeclarationSyntax delegateDeclaration)
+ {
+ CheckIdentifierName(context, delegateDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is EnumMemberDeclarationSyntax enumMemberDeclaration)
+ {
+ CheckIdentifierName(context, enumMemberDeclaration.Identifier);
+ return;
+ }
+
+ if (syntax is BaseFieldDeclarationSyntax baseFieldDeclarationSyntax)
+ {
+ var variableDeclarationSyntax = baseFieldDeclarationSyntax.Declaration;
+ if (variableDeclarationSyntax == null || variableDeclarationSyntax.IsMissing)
+ {
+ return;
+ }
+
+ foreach (var declarator in variableDeclarationSyntax.Variables)
+ {
+ if (declarator == null || declarator.IsMissing)
+ {
+ continue;
+ }
+
+ CheckIdentifierName(context, declarator.Identifier);
+ }
+ }
+ }
+
+ private static void HandleVariableDeclarationIdentifierName(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
+ {
+ var syntax = (VariableDeclarationSyntax)context.Node;
+ if (syntax.Parent.IsKind(SyntaxKind.FieldDeclaration) || syntax.Parent.IsKind(SyntaxKind.EventFieldDeclaration))
+ {
+ // This diagnostic is only for local variables.
+ return;
+ }
+
+ foreach (var variableDeclarator in syntax.Variables)
+ {
+ if (variableDeclarator is not null)
+ {
+ CheckIdentifierName(context, variableDeclarator.Identifier);
+ }
+ }
+ }
+
+ private static void HandleParameterIdentifierName(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
+ {
+ var syntax = (ParameterSyntax)context.Node;
+
+ CheckIdentifierName(context, syntax.Identifier);
+ }
+
+ private static void CheckIdentifierName(SyntaxNodeAnalysisContext context, SyntaxToken identifier)
+ {
+ var name = identifier.Text;
+
+ for (var i = 0; i < name.Length; i++)
+ {
+ if (char.IsLetter(name[i]) && name[i] is not ((>= 'a' and <= 'z') or (>= 'A' and <= 'Z')))
+ {
+ context.ReportDiagnostic(Diagnostic.Create(Descriptor, identifier.GetLocation(), name, i));
+ }
+ }
+ }
+ }
+}
diff --git a/documentation/NamingRules.md b/documentation/NamingRules.md
index ddfb5d8e4..3811a68dc 100644
--- a/documentation/NamingRules.md
+++ b/documentation/NamingRules.md
@@ -19,3 +19,4 @@ Identifier | Name | Description
[SA1313](SA1313.md) | ParameterNamesMustBeginWithLowerCaseLetter | The name of a parameter in C# does not begin with a lower-case letter.
[SA1314](SA1314.md) | TypeParameterNamesMustBeginWithT | The name of a C# type parameter does not begin with the capital letter T.
[SA1316](SA1316.md) | TupleElementNamesShouldUseCorrectCasing | Element names within a tuple type should have the correct casing.
+[SA1317](SA1317.md) | IdentifierShouldBeNamedOnlyWithLatinLetters | An identifier should be named only with Latin letters.
diff --git a/documentation/SA1317.md b/documentation/SA1317.md
new file mode 100644
index 000000000..7eac36e50
--- /dev/null
+++ b/documentation/SA1317.md
@@ -0,0 +1,55 @@
+## SA1317
+
+
+
+
TypeName
+
SA1317IdentifierShouldBeNamedOnlyWithLatinLetters
+
+
+
CheckId
+
SA1317
+
+
+
Category
+
Naming Rules
+
+
+
+## Cause
+
+An identifier should be named only with Latin letters.
+
+## Rule description
+
+An identifier should be named only with Latin letters.
+
+For example, the following code would produce a violation of this rule because identifier 'ЕxаmplеClаss' contains non-Latin letters **Е**x**а**mpl**е**Cl**а**ss:
+
+```csharp
+public class ЕxаmplеClаss
+{
+}
+```
+
+The following code would not produce any violations:
+
+```csharp
+public class ExampleClass
+{
+}
+```
+
+## How to fix violations
+
+To fix a violation of this rule, replace non-Latin letters with appropriate Latin letters.
+
+## How to suppress violations
+
+```csharp
+[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1317:IdentifierShouldBeNamedOnlyWithLatinLetters", Justification = "Reviewed.")]
+```
+
+```csharp
+#pragma warning disable SA1317 // Identifier should be named only with Latin letters
+#pragma warning restore SA1317 // Identifier should be named only with Latin letters
+```