File: ConvertToFileScopedNamespaceAnalyzerTests.cs
Web Access
Project: ..\..\..\src\CodeStyle\CSharp\Tests\Microsoft.CodeAnalysis.CSharp.CodeStyle.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.CodeStyle.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.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.ConvertNamespace;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Testing;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertNamespace
{
    using VerifyCS = CSharpCodeFixVerifier<ConvertToFileScopedNamespaceDiagnosticAnalyzer, ConvertNamespaceCodeFixProvider>;
 
    public class ConvertToFileScopedNamespaceAnalyzerTests
    {
        [Fact]
        public async Task TestNoConvertToFileScopedInCSharp9()
        {
            var code = """
                namespace N
                {
                }
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp9,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestNoConvertToFileScopedInCSharp10WithBlockScopedPreference()
        {
            var code = """
                namespace N
                {
                }
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.BlockScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedInCSharp10WithBlockScopedPreference()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                }
                """,
                FixedCode = """
                namespace $$N;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedInCSharp10WithBlockScopedPreference_NotSilent()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                namespace [|N|]
                {
                }
                """,
                FixedCode = """
                namespace $$N;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped, NotificationOption2.Suggestion }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestNoConvertWithMultipleNamespaces()
        {
            var code = """
                namespace N
                {
                }
 
                namespace N2
                {
                }
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestNoConvertWithNestedNamespaces1()
        {
            var code = """
                namespace N
                {
                    namespace N2
                    {
                    }
                }
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestNoConvertWithTopLevelStatement1()
        {
            var code = """
                {|CS8805:int i = 0;|}
 
                namespace N
                {
                }
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestNoConvertWithTopLevelStatement2()
        {
            var code = """
                namespace N
                {
                }
 
                int i = 0;
                """;
            await new VerifyCS.Test
            {
                TestCode = code,
                FixedCode = code,
                LanguageVersion = LanguageVersion.CSharp10,
                ExpectedDiagnostics =
                {
                    // /0/Test0.cs(6,1): error CS8803: Top-level statements must precede namespace and type declarations.
                    DiagnosticResult.CompilerError("CS8803").WithSpan(5, 1, 5, 11),
                    // /0/Test0.cs(6,1): error CS8805: Program using top-level statements must be an executable.
                    DiagnosticResult.CompilerError("CS8805").WithSpan(5, 1, 5, 11),
                },
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithUsing1()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                using System;
 
                [|namespace N|]
                {
                }
                """,
                FixedCode = """
                using System;
 
                namespace $$N;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithUsing2()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    using System;
                }
                """,
                FixedCode = """
                namespace $$N;
 
                using System;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithClass()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithClassWithDocComment()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    /// <summary/>
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                /// <summary/>
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithMissingCloseBrace()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    /// <summary/>
                    class C
                    {
                    }{|CS1513:|}
                """,
                FixedCode = """
                namespace N;
 
                /// <summary/>
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithCommentOnOpenCurly()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                { // comment
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
                // comment
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithLeadingComment()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                // copyright
                [|namespace N|]
                {
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                // copyright
                namespace $$N;
 
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithDocComment()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    /// <summary/>
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                /// <summary/>
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithPPDirective1()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                #if X
                    class C
                    {
                    }
                #else
                    class C
                    {
                    }
                #endif
                }
                """,
                FixedCode = """
                namespace $$N;
 
                #if X
                class C
                {
                }
                #else
                class C
                {
                }
                #endif
 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithBlockComment()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    /* x
                     * x
                     */
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                /* x
                 * x
                 */
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithBlockComment2()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    /* x
                       x
                     */
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                /* x
                   x
                 */
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithMultilineString()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                        void M()
                        {
                            System.Console.WriteLine(@"
                    a
                        b
                            c
                                d
                                    e
                                        ");
                        }
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                    void M()
                    {
                        System.Console.WriteLine(@"
                    a
                        b
                            c
                                d
                                    e
                                        ");
                    }
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithMultilineString2()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                        void M()
                        {
                            System.Console.WriteLine($@"
                    a
                        b
                            c{1 + 1}
                                d
                                    e
                                        ");
                        }
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                    void M()
                    {
                        System.Console.WriteLine($@"
                    a
                        b
                            c{1 + 1}
                                d
                                    e
                                        ");
                    }
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithMultilineString3()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                        void M()
                        {
                            System.Console.WriteLine($@"
                    a
                        b
                            c{
                                1 + 1
                             }d
                                    e
                                        ");
                        }
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                    void M()
                    {
                        System.Console.WriteLine($@"
                    a
                        b
                            c{
                            1 + 1
                         }d
                                    e
                                        ");
                    }
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithMultiLineRawString()
        {
            await new VerifyCS.Test
            {
                TestCode = """"
                [|namespace N|]
                {
                    class C
                    {
                        void M()
                        {
                            System.Console.WriteLine("""
                    a
                        b
                            c
                                d
                                    e
                    """);
                        }
                    }
                }
                """",
                FixedCode = """"
                namespace $$N;
 
                class C
                {
                    void M()
                    {
                        System.Console.WriteLine("""
                    a
                        b
                            c
                                d
                                    e
                    """);
                    }
                }
                """",
                LanguageVersion = LanguageVersion.Preview,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedWithUtf8MultiLineRawString()
        {
            await new VerifyCS.Test
            {
                TestCode = """"
                [|namespace N|]
                {
                    class C
                    {
                        void M()
                        {
                            M2("""
                    a
                        b
                            c
                                d
                                    e
                    """u8);
                        }
 
                        void M2(System.ReadOnlySpan<byte> x) {}
                    }
                }
                """",
                FixedCode = """"
                namespace $$N;
 
                class C
                {
                    void M()
                    {
                        M2("""
                    a
                        b
                            c
                                d
                                    e
                    """u8);
                    }
 
                    void M2(System.ReadOnlySpan<byte> x) {}
                }
                """",
                LanguageVersion = LanguageVersion.Preview,
                ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedSingleLineNamespace1()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|] { class C { } }
                """,
                FixedCode = """
                namespace $$N; class C { } 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task TestConvertToFileScopedSingleLineNamespace2()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                { class C { } }
                """,
                FixedCode = """
                namespace $$N;
                class C { } 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedWithNoNewlineAtEnd()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedWithNoMembersAndNoNewlineAtEnd()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                }
                """,
                FixedCode = """
                namespace $$N;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedPreserveNewlineAtEnd()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                    class C
                    {
                    }
                }
                """,
                FixedCode = """
                namespace $$N;
 
                class C
                {
                }
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedWithNoMembersPreserveNewlineAtEnd()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace N|]
                {
                }
                """,
                FixedCode = """
                namespace $$N;
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedPPDirective1()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace Goo|]
                {
                #if true
                    class goobar { }
                #endif
                // There must be no CR, LF, or other character after the brace on the following line!
                }
                """,
                FixedCode = """
                namespace $$Goo;
 
                #if true
                class goobar { }
                #endif
                // There must be no CR, LF, or other character after the brace on the following line!
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedPPDirective2()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace Goo|]
                {
                #if true
                    class goobar { }
                #endif
                // There must be no CR, LF, or other character after the brace on the following line!
                }
 
                """,
                FixedCode = """
                namespace $$Goo;
 
                #if true
                class goobar { }
                #endif
                // There must be no CR, LF, or other character after the brace on the following line!
 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedPPDirective3()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace Goo|]
                {
                #if false
                    class goobar { }
                #endif
                }
                """,
                FixedCode = """
                namespace $$Goo;
 
                #if false
                class goobar { }
                #endif
 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/59728")]
        public async Task TestConvertToFileScopedPPDirective4()
        {
            await new VerifyCS.Test
            {
                TestCode = """
                [|namespace Goo|]
                {
                #if false
                    class goobar { }
                #endif
                }
 
                """,
                FixedCode = """
                namespace $$Goo;
 
                #if false
                class goobar { }
                #endif
 
                """,
                LanguageVersion = LanguageVersion.CSharp10,
                Options =
                {
                    { CSharpCodeStyleOptions.NamespaceDeclarations, NamespaceDeclarationPreference.FileScoped }
                }
            }.RunAsync();
        }
    }
}