File: IdentifiersShouldBeSpelledCorrectlyTests.cs
Web Access
Project: src\src\RoslynAnalyzers\Text.Analyzers\UnitTests\Text.Analyzers.UnitTests.csproj (Text.Analyzers.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Text;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Text.Analyzers.IdentifiersShouldBeSpelledCorrectlyAnalyzer,
    Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
 
namespace Text.Analyzers.UnitTests
{
    public class IdentifiersShouldBeSpelledCorrectlyTests
    {
        public enum DictionaryType
        {
            Xml,
            Dic,
        }
 
        public static IEnumerable<object[]> MisspelledMembers
            => new[]
            {
                new object[] { CreateTypeWithConstructor("Clazz", constructorName: "{|#0:Clazz|}", isStatic: false), "Clazz", "Clazz.Clazz()" },
                new object[] { CreateTypeWithConstructor("Clazz", constructorName: "{|#0:Clazz|}", isStatic: true), "Clazz", "Clazz.Clazz()" },
                new object[] { CreateTypeWithField("Program", "{|#0:_fild|}"), "fild", "Program._fild" },
                new object[] { CreateTypeWithEvent("Program", "{|#0:Evt|}"), "Evt", "Program.Evt" },
                new object[] { CreateTypeWithProperty("Program", "{|#0:Naem|}"), "Naem", "Program.Naem" },
                new object[] { CreateTypeWithMethod("Program", "{|#0:SomeMathod|}"), "Mathod", "Program.SomeMathod()" },
            };
 
        public static IEnumerable<object[]> UnmeaningfulMembers
            => new[]
            {
                new object[] { CreateTypeWithConstructor("A", constructorName: "{|#0:A|}", isStatic: false), "A" },
                new object[] { CreateTypeWithConstructor("B", constructorName: "{|#0:B|}", isStatic: false), "B" },
                new object[] { CreateTypeWithField("Program", "{|#0:_c|}"), "c" },
                new object[] { CreateTypeWithEvent("Program", "{|#0:D|}"), "D" },
                new object[] { CreateTypeWithProperty("Program", "{|#0:E|}"), "E" },
                new object[] { CreateTypeWithMethod("Program", "{|#0:F|}"), "F" },
            };
 
        public static IEnumerable<object[]> MisspelledMemberParameters
            => new[]
            {
                new object[] { CreateTypeWithConstructor("Program", parameter: "int {|#0:yourNaem|}", isStatic: false), "Naem", "yourNaem", "Program.Program(int)" },
                new object[] { CreateTypeWithMethod("Program", "Method", "int {|#0:yourNaem|}"), "Naem", "yourNaem", "Program.Method(int)" },
                new object[] { CreateTypeWithIndexer("Program", "int {|#0:yourNaem|}"), "Naem", "yourNaem", "Program.this[int]" },
            };
 
        [Theory]
        [InlineData("namespace Bar { }")]
        [InlineData("class Program { }")]
        [InlineData("class Program { void Member() { } }")]
        [InlineData("class Program { int _variable = 1; }")]
        [InlineData("class Program { void Member(string name) { } }")]
        [InlineData("class Program { delegate int GetNumber(string name); }")]
        [InlineData("class Program<TResource> { }")]
        public async Task NoMisspellings_Verify_NoDiagnosticsAsync(string source)
        {
            await VerifyCSharpAsync(source);
        }
 
        [Fact]
        public async Task MisspellingAllowedByGlobalXmlDictionary_Verify_NoDiagnosticsAsync()
        {
            var source = "class Clazz { }";
            var dictionary = CreateXmlDictionary(new[] { "clazz" });
 
            await VerifyCSharpAsync(source, dictionary);
        }
 
        [Fact]
        public async Task MisspellingAllowedByGlobalDicDictionary_Verify_NoDiagnosticsAsync()
        {
            var source = "class Clazz { }";
            var dictionary = CreateDicDictionary(new[] { "clazz" });
 
            await VerifyCSharpAsync(source, dictionary);
        }
 
        [Fact]
        public async Task MisspellingsAllowedByMultipleGlobalDictionaries_Verify_NoDiagnosticsAsync()
        {
            var source = @"class Clazz { const string Naem = ""foo""; }";
            var xmlDictionary = CreateXmlDictionary(new[] { "clazz" });
            var dicDictionary = CreateDicDictionary(new[] { "naem" });
 
            await VerifyCSharpAsync(source, new[] { xmlDictionary, dicDictionary });
        }
 
        [Fact]
        public async Task CorrectWordDisallowedByGlobalXmlDictionary_Verify_EmitsDiagnosticAsync()
        {
            var source = "class {|#0:Program|} { }";
            var dictionary = CreateXmlDictionary(null, new[] { "program" });
 
            await VerifyCSharpAsync(
                source,
                dictionary,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeRule)
                    .WithLocation(0)
                    .WithArguments("Program", "Program"));
        }
 
        [Fact]
        public async Task MisspellingAllowedByProjectDictionary_Verify_NoDiagnosticsAsync()
        {
            var source = "class Clazz {}";
            var dictionary = CreateDicDictionary(new[] { "clazz" });
 
            await VerifyCSharpAsync(source, dictionary);
        }
 
        [Fact]
        public async Task MisspellingAllowedByDifferentProjectDictionary_Verify_EmitsDiagnosticAsync()
        {
            var source = "class {|#0:Clazz|} {}";
            var dictionary = CreateDicDictionary(new[] { "clazz" });
            var test = new VerifyCS.Test
            {
                TestState =
                {
                    Sources = { source },
                    AdditionalProjects =
                    {
                        ["OtherProject"] =
                        {
                            AdditionalFiles = { dictionary }
                        },
                    },
                    AdditionalProjectReferences = { "OtherProject" }
                },
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeRule)
                        .WithLocation(0)
                        .WithArguments("Clazz", "Clazz")
                }
            };
 
            await test.RunAsync();
        }
 
        [Fact]
        public async Task AssemblyMisspelled_Verify_EmitsDiagnosticAsync()
        {
            var source = "{|#0:class Program {}|}";
            var test = new VerifyCS.Test
            {
                TestState =
                {
                    Sources = { source },
                },
                SolutionTransforms =
                {
                    RenameProjectAssembly,
                },
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.AssemblyRule)
                        .WithLocation(0)
                        .WithArguments("Assambly", "MyAssambly")
                }
            };
 
            await test.RunAsync();
 
            static Solution RenameProjectAssembly(Solution solution, ProjectId projectId)
            {
                return solution.WithProjectAssemblyName(projectId, "MyAssambly");
            }
        }
 
        [Fact]
        public async Task AssemblyUnmeaningful_Verify_EmitsDiagnosticAsync()
        {
            var source = "{|#0:class Program {}|}";
            var test = new VerifyCS.Test
            {
                TestState =
                {
                    Sources = { source },
                },
                SolutionTransforms =
                {
                    RenameProjectAssembly,
                },
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.AssemblyMoreMeaningfulNameRule)
                        .WithLocation(0)
                        .WithArguments("A")
                }
            };
 
            await test.RunAsync();
 
            static Solution RenameProjectAssembly(Solution solution, ProjectId projectId)
            {
                return solution.WithProjectAssemblyName(projectId, "A");
            }
        }
 
        [Fact]
        public async Task NamespaceMisspelled_Verify_EmitsDiagnosticAsync()
        {
            var source = "namespace Tests.{|#0:MyNarmspace|} {}";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.NamespaceRule)
                    .WithLocation(0)
                    .WithArguments("Narmspace", "Tests.MyNarmspace"));
        }
 
        [Fact]
        public async Task NamespaceUnmeaningful_Verify_EmitsDiagnosticAsync()
        {
            var source = "namespace Tests.{|#0:A|} {}";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.NamespaceMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("A"));
        }
 
        [Theory]
        [InlineData("namespace MyNamespace { class {|#0:MyClazz|} {} }", "Clazz", "MyNamespace.MyClazz")]
        [InlineData("namespace MyNamespace { struct {|#0:MyStroct|} {} }", "Stroct", "MyNamespace.MyStroct")]
        [InlineData("namespace MyNamespace { enum {|#0:MyEnim|} {} }", "Enim", "MyNamespace.MyEnim")]
        [InlineData("namespace MyNamespace { interface {|#0:IMyFase|} {} }", "Fase", "MyNamespace.IMyFase")]
        [InlineData("namespace MyNamespace { delegate int {|#0:MyDelegete|}(); }", "Delegete", "MyNamespace.MyDelegete")]
        public async Task TypeMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string typeName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeRule)
                    .WithLocation(0)
                    .WithArguments(misspelling, typeName));
        }
 
        [Theory]
        [InlineData("class {|#0:A|} {}", "A")]
        [InlineData("struct {|#0:B|} {}", "B")]
        [InlineData("enum {|#0:C|} {}", "C")]
        [InlineData("interface {|#0:ID|} {}", "D")]
        [InlineData("delegate int {|#0:E|}();", "E")]
        public async Task TypeUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string typeName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(typeName));
        }
 
        [Theory]
        [MemberData(nameof(MisspelledMembers))]
        public async Task MemberMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string memberName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberRule)
                    .WithLocation(0)
                    .WithArguments(misspelling, memberName));
        }
 
        [Fact]
        public async Task MemberOverrideMisspelled_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        abstract class Parent
        {
            protected abstract string {|#0:Naem|} { get; }
 
            public abstract int {|#1:Mathod|}();
        }
 
        class Child : Parent
        {
            protected override string Naem => ""child"";
 
            public override int Mathod() => 0;
        }
 
        class Grandchild : Child
        {
            protected override string Naem => ""grandchild"";
 
            public override int Mathod() => 1;
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberRule)
                    .WithLocation(0)
                    .WithArguments("Naem", "Parent.Naem"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberRule)
                    .WithLocation(1)
                    .WithArguments("Mathod", "Parent.Mathod()"));
        }
 
        [Theory]
        [MemberData(nameof(UnmeaningfulMembers))]
        public async Task MemberUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string memberName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(memberName));
        }
 
        [Fact]
        public async Task VariableMisspelled_Verify_EmitsDiagnosticAsync()
        {
            var source = @"
        class Program
        {
            public Program()
            {
                var {|#0:myVoriable|} = 5;
            }
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.VariableRule)
                    .WithLocation(0)
                    .WithArguments("Voriable", "myVoriable"));
        }
 
        [Theory]
        [MemberData(nameof(MisspelledMemberParameters))]
        public async Task MemberParameterMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string parameterName, string memberName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments(memberName, misspelling, parameterName));
        }
 
        [Fact]
        public async Task MemberParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
        {
            var source = @"
        class Program
        {
            public void Method(string {|#0:a|})
            {
            }
 
            public string this[int {|#1:i|}] => null;
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method(string)", "a"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(1)
                    .WithArguments("Program.this[int]", "i"));
        }
 
        [Fact]
        public async Task MemberParameterMisspelledInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        interface IProgram
        {
            void Method(string {|#0:explaintain|});
 
            string this[int {|#1:indxe|}] { get; }
        }
 
        class Program : IProgram
        {
            public void Method(string explaintain)
            {
            }
 
            public string this[int indxe] => null;
 
            public void Method2(long {|#2:enviromentId|})
            {
            }
 
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments("IProgram.Method(string)", "explaintain", "explaintain"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(1)
                    .WithArguments("IProgram.this[int]", "indxe", "indxe"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(2)
                    .WithArguments("Program.Method2(long)", "enviroment", "enviromentId"));
        }
 
        [Fact]
        public async Task MemberParameterUnmeaningfulInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        interface IProgram
        {
            void Method(string {|#0:a|});
 
            string this[int {|#1:i|}] { get; }
        }
 
        class Program : IProgram
        {
            public void Method(string a)
            {
            }
 
            public string this[int i] => null;
 
            public void Method2(long {|#2:x|})
            {
            }
 
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("IProgram.Method(string)", "a"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(1)
                    .WithArguments("IProgram.this[int]", "i"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(2)
                    .WithArguments("Program.Method2(long)", "x"));
        }
 
        [Fact]
        public async Task MemberParameterUnmeaningfulExplicitInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        interface IProgram
        {
            void Method(string {|#0:a|});
 
            string this[int {|#1:i|}] { get; }
        }
 
        class Program : IProgram
        {
            void IProgram.Method(string a)
            {
            }
 
            string IProgram.this[int i] => null;
 
            public void Method2(long {|#2:x|})
            {
            }
 
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("IProgram.Method(string)", "a"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(1)
                    .WithArguments("IProgram.this[int]", "i"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(2)
                    .WithArguments("Program.Method2(long)", "x"));
        }
 
        [Fact]
        public async Task MemberParameterMisspelledExplicitInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        interface IProgram
        {
            void Method(string {|#0:explaintain|});
 
            string this[int {|#1:indxe|}] { get; }
        }
 
        class Program : IProgram
        {
            void IProgram.Method(string explaintain)
            {
            }
 
            string IProgram.this[int indxe] => null;
 
            public void Method2(long {|#2:enviromentId|})
            {
            }
 
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments("IProgram.Method(string)", "explaintain", "explaintain"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(1)
                    .WithArguments("IProgram.this[int]", "indxe", "indxe"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(2)
                    .WithArguments("Program.Method2(long)", "enviroment", "enviromentId"));
        }
 
        [Fact]
        public async Task MemberParameterMisspelledOverrideImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        public abstract class Base
        {
            public abstract void Method(string {|#0:explaintain|});
        }
 
        public class Derived : Base
        {
            public override void Method(string explaintain)
            {
            }
 
            public void Method2(long {|#1:enviromentId|})
            {
            }
 
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments("Base.Method(string)", "explaintain", "explaintain"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(1)
                    .WithArguments("Derived.Method2(long)", "enviroment", "enviromentId"));
        }
 
        [Fact]
        public async Task MemberParameterMisspelledOverrideImplementationWithNameMismatch_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        public abstract class Base
        {
            public abstract void Method(string {|#0:explaintain|});
            public abstract void Method2(string {|#1:inupts|});
        }
 
        public class Mid : Base
        {
            public override void Method(string explaintain)
            {
            }
 
            public override void Method2(string {|#2:paarmeter|})
            {
            }
        }
 
        public class Derived : Mid
        {
            public override void Method(string explanation)
            {
            }
 
            public override void Method2(string {|#3:paarmeterId|})
            {
            }
 
        }
 
        public class Derived2 : Mid
        {
            public override void Method(string {|#4:explaintaing|})
            {
            }
 
            public override void Method2(string {|#5:strValue|})
            {
            }
 
        }
 
";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments("Base.Method(string)", "explaintain", "explaintain"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(1)
                    .WithArguments("Base.Method2(string)", "inupts", "inupts"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(2)
                    .WithArguments("Mid.Method2(string)", "paarmeter", "paarmeter"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(3)
                    .WithArguments("Derived.Method2(string)", "paarmeter", "paarmeterId"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(4)
                    .WithArguments("Derived2.Method(string)", "explaintaing", "explaintaing"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(5)
                    .WithArguments("Derived2.Method2(string)", "str", "strValue"));
        }
 
        [Fact]
        public async Task MemberParameterMisspelledIndexerOVerrideWithNameMismatch_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
        {
            var source = @"
        public interface IProgram
        {
            string this[int {|#0:indxe|}] { get; }
        }
 
        public class Program : IProgram
        {
            public virtual string this[int indxe] => null;
        }
 
        public class DerivedProgram : Program
        {
            public override string this[int indxe] => null;
        }
 
        public class DerivedProgram2 : Program
        {
            public override string this[int {|#1:indexe|}] => null;
        }
 
";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments("IProgram.this[int]", "indxe", "indxe"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(1)
                    .WithArguments("DerivedProgram2.this[int]", "indexe", "indexe"));
        }
 
        [Fact]
        public async Task DelegateParameterMisspelled_Verify_EmitsDiagnosticAsync()
        {
            var source = "delegate void MyDelegate(string {|#0:firstNaem|});";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.DelegateParameterRule)
                    .WithLocation(0)
                    .WithArguments("MyDelegate", "Naem", "firstNaem"));
        }
 
        [Fact]
        public async Task DelegateParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
        {
            var source = "delegate void MyDelegate(string {|#0:a|});";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.DelegateParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("MyDelegate", "a"));
        }
 
        [Theory]
        [InlineData("class MyClass<TCorrect, {|#0:TWroong|}> { }", "MyClass<TCorrect, TWroong>", "Wroong", "TWroong")]
        [InlineData("struct MyStructure<{|#0:TWroong|}> { }", "MyStructure<TWroong>", "Wroong", "TWroong")]
        [InlineData("interface IInterface<{|#0:TWroong|}> { }", "IInterface<TWroong>", "Wroong", "TWroong")]
        [InlineData("delegate int MyDelegate<{|#0:TWroong|}>();", "MyDelegate<TWroong>", "Wroong", "TWroong")]
 
        public async Task TypeTypeParameterMisspelled_Verify_EmitsDiagnosticAsync(string source, string typeName, string misspelling, string typeParameterName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeTypeParameterRule)
                    .WithLocation(0)
                    .WithArguments(typeName, misspelling, typeParameterName));
        }
 
        [Theory]
        [InlineData("class MyClass<{|#0:A|}> { }", "MyClass<A>", "A")]
        [InlineData("struct MyStructure<{|#0:B|}> { }", "MyStructure<B>", "B")]
        [InlineData("interface IInterface<{|#0:C|}> { }", "IInterface<C>", "C")]
        [InlineData("delegate int MyDelegate<{|#0:D|}>();", "MyDelegate<D>", "D")]
        public async Task TypeTypeParameterUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string typeName, string typeParameterName)
        {
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeTypeParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(typeName, typeParameterName));
        }
 
        [Fact]
        public async Task MethodTypeParameterMisspelled_Verify_EmitsDiagnosticAsync()
        {
            var source = @"
        class Program
        {
            void Method<{|#0:TTipe|}>(TTipe item)
            {
            }
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MethodTypeParameterRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method<TTipe>(TTipe)", "Tipe", "TTipe"));
        }
 
        [Fact]
        public async Task MethodTypeParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
        {
            var source = @"
        class Program
        {
            void Method<{|#0:TA|}>(TA parameter)
            {
            }
        }";
 
            await VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MethodTypeParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method<TA>(TA)", "TA"));
        }
 
        [Fact]
        public async Task MisspellingContainsOnlyCapitalizedLetters_Verify_NoDiagnosticsAsync()
        {
            var source = "class FCCA { }";
 
            await VerifyCSharpAsync(source);
        }
 
        [Theory]
        [InlineData("0x0")]
        [InlineData("0xDEADBEEF")]
        public async Task MisspellingStartsWithADigit_Verify_NoDiagnosticsAsync(string misspelling)
        {
            var source = $"enum Name {{ My{misspelling} }}";
 
            await VerifyCSharpAsync(source);
        }
 
        [Fact]
        public async Task MalformedXmlDictionary_Verify_EmitsDiagnosticAsync()
        {
            var contents = @"<?xml version=""1.0"" encoding=""utf-8""?>
        <Dictionary>
            <Words>
                <Recognized>
                    <Word>okay</Word>
                    <word>bad</Word> <!-- xml tags are case-sensitive -->
                </Recognized>
            </Words>
        </Dictionary>";
            var dictionary = ("CodeAnalysisDictionary.xml", contents);
 
            await VerifyCSharpAsync(
                "class Program {}",
                dictionary,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.FileParseRule)
                    // Ignore diagnostic message comparison because the actual message
                    // includes localized content from an exception's message
                    .WithMessage(null));
        }
 
        private Task VerifyCSharpAsync(string source, params DiagnosticResult[] expected)
            => VerifyCSharpAsync(source, Array.Empty<(string Path, string Text)>(), expected);
 
        private Task VerifyCSharpAsync(string source, (string Path, string Text) additionalText, params DiagnosticResult[] expected)
            => VerifyCSharpAsync(source, new[] { additionalText }, expected);
 
        private async Task VerifyCSharpAsync(string source, (string Path, string Text)[] additionalTexts, params DiagnosticResult[] expected)
        {
 
            var csharpTest = new VerifyCS.Test
            {
                TestCode = source,
                TestState =
                {
                    AdditionalFilesFactories = { () => additionalTexts.Select(x => (x.Path, SourceText.From(x.Text))) }
                },
                TestBehaviors = TestBehaviors.SkipSuppressionCheck,
            };
 
            csharpTest.ExpectedDiagnostics.AddRange(expected);
 
            await csharpTest.RunAsync();
        }
 
        private static (string Path, string Text) CreateXmlDictionary(IEnumerable<string>? recognizedWords, IEnumerable<string>? unrecognizedWords = null)
            => CreateXmlDictionary("CodeAnalysisDictionary.xml", recognizedWords, unrecognizedWords);
 
        private static (string Path, string Text) CreateXmlDictionary(string filename, IEnumerable<string>? recognizedWords, IEnumerable<string>? unrecognizedWords = null)
        {
            var contents = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<Dictionary>
    <Words>
        <Recognized>{CreateXml(recognizedWords)}</Recognized>
        <Unrecognized>{CreateXml(unrecognizedWords)}</Unrecognized>
    </Words>
</Dictionary>";
 
            return (filename, contents);
 
            static string CreateXml(IEnumerable<string>? words) =>
                string.Join(Environment.NewLine, words?.Select(x => $"<Word>{x}</Word>") ?? Enumerable.Empty<string>());
        }
 
        private static (string Path, string Text) CreateDicDictionary(IEnumerable<string> recognizedWords)
        {
            var contents = string.Join(Environment.NewLine, recognizedWords);
            return ("CustomDictionary.dic", contents);
        }
 
        private static string CreateTypeWithConstructor(string typeName, string constructorName = "", string parameter = "", bool isStatic = false)
        {
            if (string.IsNullOrEmpty(constructorName))
            {
                constructorName = typeName;
            }
 
            return $@"
#pragma warning disable {IdentifiersShouldBeSpelledCorrectlyAnalyzer.RuleId}
class {typeName}
#pragma warning restore {IdentifiersShouldBeSpelledCorrectlyAnalyzer.RuleId}
{{
    {(isStatic ? "static " : string.Empty)}{constructorName}({parameter}) {{ }}
}}";
        }
 
        private static string CreateTypeWithMethod(string typeName, string methodName, string parameter = "")
            => $"class {typeName} {{ void {methodName}({parameter}) {{ }} }}";
 
        private static string CreateTypeWithIndexer(string typeName, string parameter)
            => $"class {typeName} {{ int this[{parameter}] => 0; }}";
 
        private static string CreateTypeWithProperty(string typeName, string propertyName)
            => $"class {typeName} {{ string {propertyName} {{ get; }} }}";
 
        private static string CreateTypeWithField(string typeName, string fieldName)
            => $"class {typeName} {{ private string {fieldName}; }}";
 
        private static string CreateTypeWithEvent(string typeName, string eventName)
            => $@"using System;
 
class {typeName} {{ event EventHandler<string> {eventName}; }}";
    }
}