File: Microsoft.NetCore.Analyzers\Runtime\PreferStreamWriteAsyncMemoryOverloadsTests.cs
Web Access
Project: ..\..\..\src\Microsoft.CodeAnalysis.NetAnalyzers\tests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.csproj (Microsoft.CodeAnalysis.NetAnalyzers.UnitTests)
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
 
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
 
#pragma warning disable CA1305 // Specify IFormatProvider in string.Format
 
namespace Microsoft.NetCore.Analyzers.Runtime.UnitTests
{
    public class PreferStreamWriteAsyncMemoryOverloadsTest : PreferStreamAsyncMemoryOverloadsTestBase
    {
        #region C# - No diagnostic
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_WriteAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            s.Write(buffer, 0, buffer.Length);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_WriteAsync_ByteMemoryAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            Memory<byte> memory = new Memory<byte>(buffer);
            await s.WriteAsync(memory, new CancellationToken()).ConfigureAwait(false);
       }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_WriteAsync_AsMemoryAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer.AsMemory(), new CancellationToken()).ConfigureAwait(false);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_NoAwait_SaveAsTaskAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            Task t = s.WriteAsync(buffer, 0, buffer.Length);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_FileStream_NoAwait_ReturnMethodAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public Task M(FileStream s, byte[] buffer)
    {
        return s.WriteAsync(buffer, 0, buffer.Length);
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_Stream_NoAwait_VoidMethodAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public void M(Stream s, byte[] buffer)
    {
        s.WriteAsync(buffer, 0, 1);
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_Stream_NoAwait_VoidMethod_InvokeGetBufferMethodAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public byte[] GetBuffer()
    {
        return new byte[] { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
    }
    public void M(Stream s)
    {
        s.WriteAsync(GetBuffer(), 0, 1);
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_NoAwait_ExpressionBodyMethodAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public Task M(FileStream s, byte[] buffer) => s.WriteAsync(buffer, 0, buffer.Length);
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_ContinueWith_ConfigureAwaitAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer, 0, buffer.Length).ContinueWith(c => {}).ConfigureAwait(false);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_ContinueWith_ContinueWith_ConfigureAwaitAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer, 0, buffer.Length).ContinueWith(c => {}).ContinueWith(c => {}).ConfigureAwait(false);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_AutoCastedToReadOnlyMemoryAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer);
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_AutoCastedToReadOnlyMemory_CancellationTokenAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer, new CancellationToken());
        }
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_AwaitInvocationOutsideStreamInvocationAsync()
        {
            return CSharpVerifyAnalyzerAsync(@"
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""file.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            await ProcessTask(s.WriteAsync(buffer, 0, buffer.Length, new CancellationToken())).ConfigureAwait(false);
        }
    }
 
    private async Task ProcessTask(Task writeAsyncTask)
    {
        await writeAsyncTask.ConfigureAwait(false);
    }
}
            ");
        }
 
        [Fact]
        public Task CS_Analyzer_NoDiagnostic_UnsupportedVersionAsync()
        {
            return CSharpVerifyAnalyzerForUnsupportedVersionAsync(@"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
        using (FileStream s = new FileStream(""path.txt"", FileMode.Create))
        {
            await s.WriteAsync(buffer, 0, buffer.Length);
        }
    }
}
            ");
        }
 
        #endregion
 
        #region VB - No diagnostic
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_WriteAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Private Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            s.Write(buffer, 0, buffer.Length)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_WriteAsync_AsMemoryAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            Await s.WriteAsync(buffer.AsMemory(), New CancellationToken()).ConfigureAwait(False)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_NoAwait_SaveAsTaskAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Class C
    Public Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            Dim t As Task = s.WriteAsync(buffer, 0, buffer.Length)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_FileStream_NoAwait_ReturnMethodAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Class C
    Public Function M(ByVal s As FileStream, ByVal buffer As Byte()) As Task
        Return s.WriteAsync(buffer, 0, buffer.Length)
    End Function
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_Stream_NoAwait_VoidMethodAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Class C
    Public Sub M(ByVal s As Stream, ByVal buffer As Byte())
        s.WriteAsync(buffer, 0, 1)
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_Stream_NoAwait_VoidMethod_InvokeGetBufferMethodAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
Class C
    Public Function GetBuffer() As Byte()
        Return New Byte() {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
    End Function
    Public Sub M(ByVal s As Stream)
        s.WriteAsync(GetBuffer(), 0, 1)
    End Sub
End Class
            ");
        }
 
        // The method VB_Analyzer_NoDiagnostic_NoAwait_ExpressionBodyMethod() is
        // skipped because VB does not support expression bodies for methods.
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_ContinueWith_ConfigureAwaitAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""file.txt"", FileMode.Create)
            Await s.WriteAsync(buffer, 0, buffer.Length).ContinueWith(Sub(c)
                                                                       End Sub).ConfigureAwait(False)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_ContinueWith_ContinueWith_ConfigureAwaitAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""file.txt"", FileMode.Create)
            Await s.WriteAsync(buffer, 0, buffer.Length).ContinueWith(Sub(c)
                                                                       End Sub).ContinueWith(Sub(c)
                                                                                             End Sub).ConfigureAwait(False)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_AutoCastedToReadOnlyMemoryAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
 
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            Await s.WriteAsync(buffer)
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_AutoCastedToReadOnlyMemory_CancellationTokenAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
 
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            Await s.WriteAsync(buffer, New CancellationToken())
        End Using
    End Sub
End Class
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_AwaitInvocationOutsideStreamInvocationAsync()
        {
            return VisualBasicVerifyAnalyzerAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks
 
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""file.txt"", FileMode.Open)
            Dim buffer As Byte() = { &HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await ProcessTask(s.WriteAsync(buffer, 0, buffer.Length, New CancellationToken())).ConfigureAwait(False)
        End Using
    End Sub
 
    Private Async Function ProcessTask(ByVal writeAsyncTask As Task) As Task
        Await writeAsyncTask.ConfigureAwait(False)
    End Function
End Class
 
            ");
        }
 
        [Fact]
        public Task VB_Analyzer_NoDiagnostic_UnsupportedVersionAsync()
        {
            return VisualBasicVerifyAnalyzerForUnsupportedVersionAsync(@"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
        Using s As FileStream = New FileStream(""path.txt"", FileMode.Create)
            Await s.WriteAsync(buffer, 0, buffer.Length)
        End Using
    End Sub
End Class
            ");
        }
 
        #endregion
 
        #region C# - Diagnostic
 
        private const string _sourceCSharp = @"
using System;
using System.IO;
using System.Threading;
class C
{{
    public async void M()
    {{
        using ({0} s = new FileStream(""path.txt"", FileMode.Create))
        {{
            {1}
            await s.WriteAsync({2}){3};
        }}
    }}
}}
            ";
 
        public static IEnumerable<object[]> CSharpInlinedByteArrayTestData()
        {
            yield return new object[] { "new byte[]{ 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 }, 0, 8",
                                        "(new byte[]{ 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 }).AsMemory(0, 8)" };
            yield return new object[] { "new byte[]{ 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 }, 0, 8, new CancellationToken()",
                                        "(new byte[]{ 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 }).AsMemory(0, 8), new CancellationToken()" };
        }
 
        [WindowsOnlyFact] // https://github.com/dotnet/roslyn/issues/65081
        public Task CS_Fixer_Diagnostic_EnsureSystemNamespaceAutoAddedAsync()
        {
            string originalCode = @"
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            await s.WriteAsync(buffer, 1, buffer.Length);
        }
    }
}";
            string fixedCode = @"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            await s.WriteAsync(buffer.AsMemory(1, buffer.Length));
        }
    }
}";
            return CSharpVerifyExpectedCodeFixDiagnosticsAsync(originalCode, fixedCode, GetCSharpResult(11, 19, 11, 57));
        }
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(CSharpUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        public Task CS_Fixer_Diagnostic_ArgumentNamingAsync(string originalArgs, string fixedArgs) =>
            CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(CSharpUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        public Task CS_Fixer_Diagnostic_ArgumentNaming_WithConfigureAwaitAsync(string originalArgs, string fixedArgs) =>
            CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: false);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(CSharpUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        public Task CS_Fixer_Diagnostic_AsStreamAsync(string originalArgs, string fixedArgs) =>
            CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "Stream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(CSharpUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(CSharpNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        public Task CS_Fixer_Diagnostic_AsStream_WithConfigureAwaitAsync(string originalArgs, string fixedArgs) =>
            CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "Stream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: false);
 
        [Theory]
        [MemberData(nameof(CSharpInlinedByteArrayTestData))]
        public Task CS_Fixer_Diagnostic_InlineByteArrayAsync(string originalArgs, string fixedArgs)
            => CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: true, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(CSharpInlinedByteArrayTestData))]
        public Task CS_Fixer_Diagnostic_InlineByteArray_WithConfigureAwaitAsync(string originalArgs, string fixedArgs)
            => CSharpVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: true, isEmptyConfigureAwait: false);
 
        [Fact]
        public Task CS_Fixer_Diagnostic_WithTriviaAsync()
        {
            // Notes:
            // The invocation trivia is not part of the squiggle
            // If trivia is added before a method argument, it does not get saved as "leading trivia" for the argument, which is why this test only verifies argument trailing trivia
            // Trivia from await should remain untouched
            string originalSource = @"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            /* AwaitLeadingTrivia */ await /* InvocationLeadingTrivia */ s.WriteAsync(buffer /* BufferTrailingTrivia */, 1 /* OffsetTrailingTrivia */, buffer.Length /* CountTrailingTrivia */, new CancellationToken() /* CancellationTokenTrailingTrivia */) /* InvocationTrailingTrivia */; /* AwaitTrailingTrivia */
        }
    }
}
            ";
 
            string fixedSource = @"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            /* AwaitLeadingTrivia */ await /* InvocationLeadingTrivia */ s.WriteAsync(buffer.AsMemory(1 /* OffsetTrailingTrivia */, buffer.Length /* CountTrailingTrivia */) /* BufferTrailingTrivia */, new CancellationToken() /* CancellationTokenTrailingTrivia */) /* InvocationTrailingTrivia */; /* AwaitTrailingTrivia */
        }
    }
}
            ";
 
            return CSharpVerifyExpectedCodeFixDiagnosticsAsync(originalSource, fixedSource, GetCSharpResult(12, 74, 12, 255));
        }
 
        [Fact]
        public Task CS_Fixer_Diagnostic_WithTrivia_WithConfigureAwaitAsync()
        {
            // Notes:
            // The invocation trivia is not part of the squiggle
            // If trivia is added before a method argument, it does not get saved as "leading trivia" for the argument, which is why this test only verifies argument trailing trivia
            // Trivia from await and ConfigureAwait should remain untouched
            string originalSource = @"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            /* AwaitLeadingTrivia */ await /* InvocationLeadingTrivia */ s.WriteAsync(buffer /* BufferTrailingTrivia */, 1 /* OffsetTrailingTrivia */, buffer.Length /* CountTrailingTrivia */, new CancellationToken() /* CancellationTokenTrailingTrivia */).ConfigureAwait(/* ConfigureAwaitArgLeadingTrivia */ false /* ConfigureAwaitArgTrailngTrivia */) /* InvocationTrailingTrivia */; /* AwaitTrailingTrivia */
        }
    }
}
            ";
 
            string fixedSource = @"
using System;
using System.IO;
using System.Threading;
class C
{
    public async void M()
    {
        using (FileStream s = File.Open(""path.txt"", FileMode.Open))
        {
            byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };
            /* AwaitLeadingTrivia */ await /* InvocationLeadingTrivia */ s.WriteAsync(buffer.AsMemory(1 /* OffsetTrailingTrivia */, buffer.Length /* CountTrailingTrivia */) /* BufferTrailingTrivia */, new CancellationToken() /* CancellationTokenTrailingTrivia */).ConfigureAwait(/* ConfigureAwaitArgLeadingTrivia */ false /* ConfigureAwaitArgTrailngTrivia */) /* InvocationTrailingTrivia */; /* AwaitTrailingTrivia */
        }
    }
}
            ";
 
            return CSharpVerifyExpectedCodeFixDiagnosticsAsync(originalSource, fixedSource, GetCSharpResult(12, 74, 12, 255));
        }
 
        [Fact]
        public Task CS_Fixer_PreserveNullabilityAsync()
        {
            // The difference with the ReadAsync test is buffer?.Length
            string originalSource = @"
#nullable enable
using System;
using System.IO;
using System.Threading.Tasks;
 
public class C
{
    async ValueTask M(Stream? stream, byte[]? buffer)
    {
        await stream!.WriteAsync(buffer!, offset: 0, count: buffer?.Length ?? 0).ConfigureAwait(false);
    }
}
";
            string fixedSource = @"
#nullable enable
using System;
using System.IO;
using System.Threading.Tasks;
 
public class C
{
    async ValueTask M(Stream? stream, byte[]? buffer)
    {
        await stream!.WriteAsync(buffer!.AsMemory(start: 0, length: buffer?.Length ?? 0)).ConfigureAwait(false);
    }
}
";
 
            return CSharpVerifyForVersionAsync(
                originalSource,
                fixedSource,
                ReferenceAssemblies.Net.Net50,
                CodeAnalysis.CSharp.LanguageVersion.CSharp8,
                GetCSharpResult(11, 15, 11, 81));
        }
 
        [Fact]
        public Task CS_Fixer_PreserveNullabilityWithCancellationTokenAsync()
        {
            // The difference with the ReadAsync test is buffer?.Length
            string originalSource = @"
#nullable enable
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
 
public class C
{
    async ValueTask M(Stream? stream, byte[]? buffer, CancellationToken ct)
    {
        await stream!.WriteAsync(buffer!, offset: 0, count: buffer?.Length ?? 0, ct).ConfigureAwait(false);
    }
}
";
            string fixedSource = @"
#nullable enable
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
 
public class C
{
    async ValueTask M(Stream? stream, byte[]? buffer, CancellationToken ct)
    {
        await stream!.WriteAsync(buffer!.AsMemory(start: 0, length: buffer?.Length ?? 0), ct).ConfigureAwait(false);
    }
}
";
 
            return CSharpVerifyForVersionAsync(
                originalSource,
                fixedSource,
                ReferenceAssemblies.Net.Net50,
                CodeAnalysis.CSharp.LanguageVersion.CSharp8,
                GetCSharpResult(12, 15, 12, 85));
        }
 
        #endregion
 
        #region VB - Diagnostic
 
        private const string _sourceVisualBasic = @"
Imports System
Imports System.IO
Imports System.Threading
Public Module C
    Public Async Sub M()
        Using s As {0} = New FileStream(""file.txt"", FileMode.Create)
            {1}
            Await s.WriteAsync({2}){3}
        End Using
    End Sub
End Module
            ";
 
        public static IEnumerable<object[]> VisualBasicInlinedByteArrayTestData()
        {
            yield return new object[] { @"New Byte() {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}, 0, 8",
                                        @"(New Byte() {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}).AsMemory(0, 8)" };
            yield return new object[] { @"New Byte() {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}, 0, 8, New CancellationToken()",
                                        @"(New Byte() {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}).AsMemory(0, 8), New CancellationToken()" };
        }
 
        [WindowsOnlyFact] // https://github.com/dotnet/roslyn/issues/65081
        public Task VB_Fixer_Diagnostic_EnsureSystemNamespaceAutoAddedAsync()
        {
            string originalCode = @"
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync(buffer, 1, buffer.Length)
        End Using
    End Sub
End Class
";
            string fixedCode = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync(buffer.AsMemory(1, buffer.Length))
        End Using
    End Sub
End Class
";
            return VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(originalCode, fixedCode, GetVisualBasicResult(8, 19, 8, 57));
        }
 
        [Theory]
        [InlineData("System")]
        [InlineData("system")]
        [InlineData("SYSTEM")]
        [InlineData("sYSTEm")]
        public Task VB_Fixer_Diagnostic_EnsureSystemNamespaceNotAddedWhenAlreadyPresentAsync(string systemNamespace)
        {
            string originalCode = $@"
Imports System.IO
Imports System.Threading
Imports {systemNamespace}
 
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {{&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}}
            Await s.WriteAsync(buffer, 1, buffer.Length)
        End Using
    End Sub
End Class
";
            string fixedCode = $@"
Imports System.IO
Imports System.Threading
Imports {systemNamespace}
 
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {{&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}}
            Await s.WriteAsync(buffer.AsMemory(1, buffer.Length))
        End Using
    End Sub
End Class
";
 
            return VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(originalCode, fixedCode, GetVisualBasicResult(10, 19, 10, 57));
        }
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(VisualBasicUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWrongCaseTestData))]
        public Task VB_Fixer_Diagnostic_ArgumentNamingAsync(string originalArgs, string fixedArgs) =>
            VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(VisualBasicUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWrongCaseTestData))]
        public Task VB_Fixer_Diagnostic_ArgumentNaming_WithConfigureAwaitAsync(string originalArgs, string fixedArgs) =>
            VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: false);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenFullBufferTestData))]
        public Task VB_Fixer_Diagnostic_AsStreamAsync(string originalArgs, string fixedArgs) =>
            VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "Stream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(UnnamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsFullBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenFullBufferTestData))]
        [MemberData(nameof(VisualBasicUnnamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWithCancellationTokenPartialBufferTestData))]
        [MemberData(nameof(VisualBasicNamedArgumentsWrongCaseTestData))]
        public Task VB_Fixer_Diagnostic_AsStream_WithConfigureAwaitAsync(string originalArgs, string fixedArgs) =>
            VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "Stream", isEmptyByteDeclaration: false, isEmptyConfigureAwait: false);
 
        [Theory]
        [MemberData(nameof(VisualBasicInlinedByteArrayTestData))]
        public Task VB_Fixer_Diagnostic_InlineByteArrayAsync(string originalArgs, string fixedArgs)
            => VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: true, isEmptyConfigureAwait: true);
 
        [Theory]
        [MemberData(nameof(VisualBasicInlinedByteArrayTestData))]
        public Task VB_Fixer_Diagnostic_InlineByteArray_WithConfigureAwaitAsync(string originalArgs, string fixedArgs)
            => VisualBasicVerifyCodeFixAsync(originalArgs, fixedArgs, streamTypeName: "FileStream", isEmptyByteDeclaration: true, isEmptyConfigureAwait: false);
 
        [Fact]
        public Task VB_Fixer_Diagnostic_WithTriviaAsync()
        {
            // Notes:
            // - Visual Basic does not allow inline comments like in C#: /**/, only at the end of the line
            // - Only the last comment in the arguments section remains ("CancellationTokenComment"), the rest get discarded
            string originalSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync( ' OpeningParenthesisComment
                buffer, ' BufferComment
                1, ' OffsetComment
                buffer.Length, ' CountComment
                New CancellationToken() ' CancellationTokenComment
                ) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            string fixedSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync(buffer.AsMemory(1, buffer.Length), New CancellationToken() ' CancellationTokenComment
) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            return VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(originalSource, fixedSource, GetVisualBasicResult(9, 19, 14, 18));
        }
 
        [Fact]
        public Task VB_Fixer_Diagnostic_WithTrivia_WithConfigureAwait_PartialBufferAsync()
        {
            // Notes:
            // - Visual Basic does not allow inline comments like in C#: /**/, only at the end of the line
            // - Only the last comment in the arguments section remains ("CancellationTokenComment"), the rest get discarded
            string originalSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync( ' OpeningParenthesisComment
                buffer, ' BufferComment
                1, ' OffsetComment
                buffer.Length, ' CountComment
                New CancellationToken() ' CancellationTokenComment
                ).ConfigureAwait(False) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            string fixedSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync(buffer.AsMemory(1, buffer.Length), New CancellationToken() ' CancellationTokenComment
).ConfigureAwait(False) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            return VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(originalSource, fixedSource, GetVisualBasicResult(9, 19, 14, 18));
        }
 
        [Fact]
        public Task VB_Fixer_Diagnostic_WithTrivia_WithConfigureAwait_FullBufferAsync()
        {
            // Notes:
            // - Visual Basic does not allow inline comments like in C#: /**/, only at the end of the line
            // - Only the last comment in the arguments section remains ("CancellationTokenComment"), the rest get discarded
            string originalSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync( ' OpeningParenthesisComment
                buffer, ' BufferComment
                0, ' OffsetComment
                buffer.Length, ' CountComment
                New CancellationToken() ' CancellationTokenComment
                ).ConfigureAwait(False) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            string fixedSource = @"
Imports System
Imports System.IO
Imports System.Threading
Class C
    Public Async Sub M()
        Using s As FileStream = File.Open(""path.txt"", FileMode.Open)
            Dim buffer As Byte() = {&HBA, &H5E, &HBA, &H11, &HF0, &H07, &HBA, &H11}
            Await s.WriteAsync(buffer, New CancellationToken() ' CancellationTokenComment
).ConfigureAwait(False) ' InvocationTrailingComment
            ' AwaitComment
        End Using
    End Sub
End Class
            ";
 
            return VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(originalSource, fixedSource, GetVisualBasicResult(9, 19, 14, 18));
        }
 
        #endregion
 
        #region Helpers
 
        private const int _columnBeforeStreamInvocation = 19;
        private readonly int _columnsBeforeArguments = _columnBeforeStreamInvocation + " s.WriteAsync(".Length;
 
        private Task CSharpVerifyCodeFixAsync(string originalArgs, string fixedArgs, string streamTypeName, bool isEmptyByteDeclaration, bool isEmptyConfigureAwait) =>
            CSharpVerifyExpectedCodeFixDiagnosticsAsync(
                string.Format(_sourceCSharp, streamTypeName, GetByteArrayWithDataCSharp(isEmptyByteDeclaration), originalArgs, GetConfigureAwaitCSharp(isEmptyConfigureAwait)),
                string.Format(_sourceCSharp, streamTypeName, GetByteArrayWithDataCSharp(isEmptyByteDeclaration), fixedArgs, GetConfigureAwaitCSharp(isEmptyConfigureAwait)),
                GetCSharpResult(12, _columnBeforeStreamInvocation, 12, _columnsBeforeArguments + originalArgs.Length));
 
        private Task VisualBasicVerifyCodeFixAsync(string originalArgs, string fixedArgs, string streamTypeName, bool isEmptyByteDeclaration, bool isEmptyConfigureAwait) =>
            VisualBasicVerifyExpectedCodeFixDiagnosticsAsync(
                string.Format(_sourceVisualBasic, streamTypeName, GetByteArrayWithDataVisualBasic(isEmptyByteDeclaration), originalArgs, GetConfigureAwaitVisualBasic(isEmptyConfigureAwait)),
                string.Format(_sourceVisualBasic, streamTypeName, GetByteArrayWithDataVisualBasic(isEmptyByteDeclaration), fixedArgs, GetConfigureAwaitVisualBasic(isEmptyConfigureAwait)),
                GetVisualBasicResult(9, _columnBeforeStreamInvocation, 9, _columnsBeforeArguments + originalArgs.Length));
 
        // Returns a C# diagnostic result using the specified rule, lines, columns and preferred method signature for the WriteAsync method.
        protected DiagnosticResult GetCSharpResult(int startLine, int startColumn, int endLine, int endColumn)
            => GetCSResultForRule(startLine, startColumn, endLine, endColumn,
                PreferStreamAsyncMemoryOverloads.PreferStreamWriteAsyncMemoryOverloadsRule,
                "WriteAsync", "Stream.WriteAsync(ReadOnlyMemory<byte>, CancellationToken)");
 
        // Returns a VB diagnostic result using the specified rule, lines, columns and preferred method signature for the WriteAsync method.
        protected DiagnosticResult GetVisualBasicResult(int startLine, int startColumn, int endLine, int endColumn)
            => GetVBResultForRule(startLine, startColumn, endLine, endColumn,
                PreferStreamAsyncMemoryOverloads.PreferStreamWriteAsyncMemoryOverloadsRule,
                "WriteAsync", "Stream.WriteAsync(ReadOnlyMemory(Of Byte), CancellationToken)");
 
        #endregion
    }
}