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 object[] { CreateTypeWithConstructor("Clazz", constructorName: "{|#0:Clazz|}", isStatic: false), "Clazz", "Clazz.Clazz()" },
                [CreateTypeWithConstructor("Clazz", constructorName: "{|#0:Clazz|}", isStatic: true), "Clazz", "Clazz.Clazz()"],
                [CreateTypeWithField("Program", "{|#0:_fild|}"), "fild", "Program._fild"],
                [CreateTypeWithEvent("Program", "{|#0:Evt|}"), "Evt", "Program.Evt"],
                [CreateTypeWithProperty("Program", "{|#0:Naem|}"), "Naem", "Program.Naem"],
                [CreateTypeWithMethod("Program", "{|#0:SomeMathod|}"), "Mathod", "Program.SomeMathod()"],
            ];
 
        public static IEnumerable<object[]> UnmeaningfulMembers
            =>
            [
                new object[] { CreateTypeWithConstructor("A", constructorName: "{|#0:A|}", isStatic: false), "A" },
                [CreateTypeWithConstructor("B", constructorName: "{|#0:B|}", isStatic: false), "B"],
                [CreateTypeWithField("Program", "{|#0:_c|}"), "c"],
                [CreateTypeWithEvent("Program", "{|#0:D|}"), "D"],
                [CreateTypeWithProperty("Program", "{|#0:E|}"), "E"],
                [CreateTypeWithMethod("Program", "{|#0:F|}"), "F"],
            ];
 
        public static IEnumerable<object[]> MisspelledMemberParameters
            =>
            [
                new object[] { CreateTypeWithConstructor("Program", parameter: "int {|#0:yourNaem|}", isStatic: false), "Naem", "yourNaem", "Program.Program(int)" },
                [CreateTypeWithMethod("Program", "Method", "int {|#0:yourNaem|}"), "Naem", "yourNaem", "Program.Method(int)"],
                [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 Task NoMisspellings_Verify_NoDiagnosticsAsync(string source)
            => VerifyCSharpAsync(source);
 
        [Fact]
        public async Task MisspellingAllowedByGlobalXmlDictionary_Verify_NoDiagnosticsAsync()
        {
            var dictionary = CreateXmlDictionary(["clazz"]);
 
            await VerifyCSharpAsync("class Clazz { }", dictionary);
        }
 
        [Fact]
        public async Task MisspellingAllowedByGlobalDicDictionary_Verify_NoDiagnosticsAsync()
        {
            var dictionary = CreateDicDictionary(["clazz"]);
 
            await VerifyCSharpAsync("class Clazz { }", dictionary);
        }
 
        [Fact]
        public async Task MisspellingsAllowedByMultipleGlobalDictionaries_Verify_NoDiagnosticsAsync()
        {
            var xmlDictionary = CreateXmlDictionary(["clazz"]);
            var dicDictionary = CreateDicDictionary(["naem"]);
 
            await VerifyCSharpAsync(@"class Clazz { const string Naem = ""foo""; }", [xmlDictionary, dicDictionary]);
        }
 
        [Fact]
        public async Task CorrectWordDisallowedByGlobalXmlDictionary_Verify_EmitsDiagnosticAsync()
        {
            var dictionary = CreateXmlDictionary(null, ["program"]);
 
            await VerifyCSharpAsync(
                "class {|#0:Program|} { }",
                dictionary,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeRule)
                    .WithLocation(0)
                    .WithArguments("Program", "Program"));
        }
 
        [Fact]
        public async Task MisspellingAllowedByProjectDictionary_Verify_NoDiagnosticsAsync()
        {
            var dictionary = CreateDicDictionary(["clazz"]);
 
            await VerifyCSharpAsync("class Clazz {}", dictionary);
        }
 
        [Fact]
        public async Task MisspellingAllowedByDifferentProjectDictionary_Verify_EmitsDiagnosticAsync()
        {
            var source = "class {|#0:Clazz|} {}";
            var dictionary = CreateDicDictionary(["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 Task NamespaceMisspelled_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                "namespace Tests.{|#0:MyNarmspace|} {}",
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.NamespaceRule)
                    .WithLocation(0)
                    .WithArguments("Narmspace", "Tests.MyNarmspace"));
 
        [Fact]
        public Task NamespaceUnmeaningful_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                "namespace Tests.{|#0:A|} {}",
                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 Task TypeMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string typeName)
            => 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 Task TypeUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string typeName)
            => VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(typeName));
 
        [Theory]
        [MemberData(nameof(MisspelledMembers))]
        public Task MemberMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string memberName)
            => VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberRule)
                    .WithLocation(0)
                    .WithArguments(misspelling, memberName));
 
        [Fact]
        public Task MemberOverrideMisspelled_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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;
                }
                """,
                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 Task MemberUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string memberName)
            => VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(memberName));
 
        [Fact]
        public Task VariableMisspelled_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                """
                class Program
                {
                    public Program()
                    {
                        var {|#0:myVoriable|} = 5;
                    }
                }
                """,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.VariableRule)
                    .WithLocation(0)
                    .WithArguments("Voriable", "myVoriable"));
 
        [Theory]
        [MemberData(nameof(MisspelledMemberParameters))]
        public Task MemberParameterMisspelled_Verify_EmitsDiagnosticAsync(string source, string misspelling, string parameterName, string memberName)
            => VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterRule)
                    .WithLocation(0)
                    .WithArguments(memberName, misspelling, parameterName));
 
        [Fact]
        public Task MemberParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                """
                class Program
                {
                    public void Method(string {|#0:a|})
                    {
                    }
 
                    public string this[int {|#1:i|}] => null;
                }
                """,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method(string)", "a"),
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MemberParameterMoreMeaningfulNameRule)
                    .WithLocation(1)
                    .WithArguments("Program.this[int]", "i"));
 
        [Fact]
        public Task MemberParameterMisspelledInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterUnmeaningfulInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterUnmeaningfulExplicitInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterMisspelledExplicitInterfaceImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterMisspelledOverrideImplementation_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterMisspelledOverrideImplementationWithNameMismatch_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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|})
                    {
                    }
 
                }
                """,
                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 Task MemberParameterMisspelledIndexerOVerrideWithNameMismatch_Verify_EmitsDiagnosticOnlyAtDefinitionAsync()
            => VerifyCSharpAsync(
                """
                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;
                }
                """,
                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 Task DelegateParameterMisspelled_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                "delegate void MyDelegate(string {|#0:firstNaem|});",
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.DelegateParameterRule)
                    .WithLocation(0)
                    .WithArguments("MyDelegate", "Naem", "firstNaem"));
 
        [Fact]
        public Task DelegateParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                "delegate void MyDelegate(string {|#0:a|});",
                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 Task TypeTypeParameterMisspelled_Verify_EmitsDiagnosticAsync(string source, string typeName, string misspelling, string typeParameterName)
            => 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 Task TypeTypeParameterUnmeaningful_Verify_EmitsDiagnosticAsync(string source, string typeName, string typeParameterName)
            => VerifyCSharpAsync(
                source,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.TypeTypeParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments(typeName, typeParameterName));
 
        [Fact]
        public Task MethodTypeParameterMisspelled_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                """
                class Program
                {
                    void Method<{|#0:TTipe|}>(TTipe item)
                    {
                    }
                }
                """,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MethodTypeParameterRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method<TTipe>(TTipe)", "Tipe", "TTipe"));
 
        [Fact]
        public Task MethodTypeParameterUnmeaningful_Verify_EmitsDiagnosticAsync()
            => VerifyCSharpAsync(
                """
                class Program
                {
                    void Method<{|#0:TA|}>(TA parameter)
                    {
                    }
                }
                """,
                VerifyCS.Diagnostic(IdentifiersShouldBeSpelledCorrectlyAnalyzer.MethodTypeParameterMoreMeaningfulNameRule)
                    .WithLocation(0)
                    .WithArguments("Program.Method<TA>(TA)", "TA"));
 
        [Fact]
        public Task MisspellingContainsOnlyCapitalizedLetters_Verify_NoDiagnosticsAsync()
            => VerifyCSharpAsync("class FCCA { }");
 
        [Theory]
        [InlineData("0x0")]
        [InlineData("0xDEADBEEF")]
        public Task MisspellingStartsWithADigit_Verify_NoDiagnosticsAsync(string misspelling)
            => VerifyCSharpAsync($"enum Name {{ My{misspelling} }}");
 
        [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, [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)
        {
            return (filename, $"""
                <?xml version="1.0" encoding="utf-8"?>
                <Dictionary>
                    <Words>
                        <Recognized>{CreateXml(recognizedWords)}</Recognized>
                        <Unrecognized>{CreateXml(unrecognizedWords)}</Unrecognized>
                    </Words>
                </Dictionary>
                """);
 
            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}}; }
            """;
    }
}