<commit_before>﻿namespace StyleCop.Analyzers.Test.SpacingRules
{
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;

    using Microsoft.CodeAnalysis.Diagnostics;

    using StyleCop.Analyzers.SpacingRules;

    using TestHelper;

    using Xunit;

    /// <summary>
    /// This class contains unit tests for the <see cref="SA1019MemberAccessSymbolsMustBeSpacedCorrectly"/> class.
    /// </summary>
    public class SA1019UnitTests : CodeFixVerifier
    {
        /// <summary>
        /// Verifies that the analyzer will properly handle an empty source.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestEmptySourceAsync()
        {
            var testCode = string.Empty;
            await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space before a period member access symbol reports correctly.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestSpaceBeforeDotAsync()
        {
            string template = this.GetTemplate(" .");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 27).WithArguments(".", "preceded");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space after a period member access symbol reports correctly.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestSpaceAfterDotAsync()
        {
            string template = this.GetTemplate(". ");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 26).WithArguments(".", "followed");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space before a null conditional access symbol reports correctly.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestSpaceBeforeNullConditionalAsync()
        {
            string template = this.GetTemplate(" ?.");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 27).WithArguments("?", "preceded");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space after a null conditional access symbol reports correctly.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestSpaceAfterNullConditionalAsync()
        {
            string template = this.GetTemplate("?. ");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 27).WithArguments(".", "followed");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a dot at the end of a line does not report.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestDotAtEndOfLineDoesNotReportAsync()
        {
            string template = this.GetTemplate($".{Environment.NewLine}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a dot at the start of a line does not report.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestDotAtStartOfLineDoesNotReportAsync()
        {
            string template = this.GetTemplate($"{Environment.NewLine}.");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a ternary operator does not report.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestTernaryDoesNotReportAsync()
        {
            string template =

@"namespace SA1019
{
    class Test
    {
        public void TestMethod()
        {
            var number = true ? 1 : 2;
        }
    }
}";

            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Gets the C# analyzers being tested
        /// </summary><commit_msg>Added some additional tests to handle comments on either side of the member access operator.<commit_after>﻿namespace StyleCop.Analyzers.Test.SpacingRules
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;

    using Microsoft.CodeAnalysis.Diagnostics;

    using StyleCop.Analyzers.SpacingRules;

    using TestHelper;

    using Xunit;

    /// <summary>
    /// This class contains unit tests for the <see cref="SA1019MemberAccessSymbolsMustBeSpacedCorrectly"/> class.
    /// </summary>
    public class SA1019UnitTests : CodeFixVerifier
    {
        /// <summary>
        /// The members access operators to test.
        /// </summary>
        /// <value>The members access operators to test.</value>
        public static IEnumerable<object[]> Operators
        {
            get
            {
                yield return new object[] { "." };
                yield return new object[] { "?." };
            }
        }

        /// <summary>
        /// Verifies that the analyzer will properly handle an empty source.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestEmptySourceAsync()
        {
            var testCode = string.Empty;
            await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space before a member access operator reports correctly.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestSpaceBeforeOperatorAsync(string op)
        {
            string template = this.GetTemplate($" {op}");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 27).WithArguments(op[0], "preceded");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a space after a member access operator reports correctly.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestSpaceAfterOperatorAsync(string op)
        {
            string template = this.GetTemplate($"{op} ");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 25 + op.Length).WithArguments(op.Last(), "followed");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a member access operator at the end of a line does not report.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestOperatorAtEndOfLineDoesNotReportAsync(string op)
        {
            string template = this.GetTemplate($"{op}{Environment.NewLine}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a member access operator at the start of a line does not report.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestOperatorAtStartOfLineDoesNotReportAsync(string op)
        {
            string template = this.GetTemplate($"{Environment.NewLine}{op}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that block comments either side of the operator does not report a diagnostic.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestBlockCommentsEitherSideOfOperatorDoesNotReportAsync(string op)
        {
            string template = this.GetTemplate($"/**/{op}/**/");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a comment on the line preceding the operator does not report.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestCommentOnLinePrecedingOperatorDoesNotReportAsync(string op)
        {
            string template = this.GetTemplate($"// This is a comment{Environment.NewLine}{op}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a comment on the line following the operator does not report.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestCommentOnLineFollowingOperatorDoesNotReportAsync(string op)
        {
            string template = this.GetTemplate($"{op}{Environment.NewLine}// This is a comment{Environment.NewLine}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a comment on the same line as the operator separated by whitespace does report a diagnostic.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestCommentOnSameLineSeparatedByWhitespaceReportsAsync(string op)
        {
            string template = this.GetTemplate($"{op} // This is a comment{Environment.NewLine}");
            DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(16, 25 + op.Length).WithArguments(".", "followed");
            await this.VerifyCSharpDiagnosticAsync(template, expected, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a comment on the same line as and immediately after the operator does report a diagnostic.
        /// </summary>
        /// <param name="op">The member access operator.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Theory]
        [MemberData(nameof(Operators))]
        public async Task TestCommentOnSameLineImmediatelyAfterOperatorDoesNotReportsAsync(string op)
        {
            string template = this.GetTemplate($"{op}// This is a comment{Environment.NewLine}");
            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Asserts that a ternary operator does not report.
        /// </summary>
        /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
        [Fact]
        public async Task TestTernaryDoesNotReportAsync()
        {
            string template =

@"namespace SA1019
{
    class Test
    {
        public void TestMethod()
        {
            var number = true ? 1 : 2;
        }
    }
}";

            await this.VerifyCSharpDiagnosticAsync(template, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
        }

        /// <summary>
        /// Gets the C# analyzers being tested
        /// </summary>
{'fraction_non_alphanumeric': 0.11375507835171213, 'fraction_numerical': 0.004135229251305862, 'mean_word_length': 2.4265473527218493, 'pattern_counts': {'":': 0, '<': 131, '<?xml version=': 0, '>': 131, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6543162', 'n_tokens_mistral': 3551, 'n_tokens_neox': 3465, 'n_words': 921}