File: CodeGeneration\CodeGenerationTests.VisualBasic.cs
Web Access
Project: src\src\EditorFeatures\Test\Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.EditorFeatures.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.
 
#nullable disable
 
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using VB = Microsoft.CodeAnalysis.VisualBasic;
 
namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeGeneration;
 
public sealed partial class CodeGenerationTests
{
    [UseExportProvider]
    public class VisualBasic
    {
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddNamespace()
            => TestAddNamespaceAsync("Namespace [|N1|]\n End Namespace", """
                Namespace N1
                    Namespace N2
                    End Namespace
                End Namespace
                """,
                name: "N2");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddField()
            => TestAddFieldAsync("Class [|C|]\n End Class", """
                Class C
                    Public F As Integer
                End Class
                """,
                type: GetTypeSymbol(typeof(int)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddSharedField()
            => TestAddFieldAsync("Class [|C|]\n End Class", """
                Class C
                    Private Shared F As String
                End Class
                """,
                type: GetTypeSymbol(typeof(string)),
                accessibility: Accessibility.Private,
                modifiers: new DeclarationModifiers(isStatic: true));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddArrayField()
            => TestAddFieldAsync("Class [|C|]\n End Class", """
                Class C
                    Public F As Integer()
                End Class
                """,
                type: CreateArrayType(typeof(int)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddConstructor()
            => TestAddConstructorAsync("Class [|C|]\n End Class", """
                Class C
                    Public Sub New()
                    End Sub
                End Class
                """);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530785")]
        public Task AddConstructorWithXmlComment()
            => TestAddConstructorAsync("""
                Public Class [|C|]
                ''' <summary>
                ''' Do Nothing
                ''' </summary>
                Public Sub GetStates()
                End Sub
                End Class
                """, """
                Public Class C
                    Public Sub New()
                    End Sub
                    ''' <summary>
                    ''' Do Nothing
                    ''' </summary>
                    Public Sub GetStates()
                End Sub
                End Class
                """);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddConstructorWithoutBody()
            => TestAddConstructorAsync("Class [|C|]\n End Class", """
                Class C
                    Public Sub New()
                End Class
                """,
                context: new CodeGenerationContext(generateMethodBodies: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddConstructorResolveNamespaceImport()
            => TestAddConstructorAsync("Class [|C|]\n End Class", """
                Imports System.Text
 
                Class C
                    Public Sub New(s As StringBuilder)
                    End Sub
                End Class
                """,
                parameters: Parameters(Parameter(typeof(StringBuilder), "s")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddSharedConstructor()
            => TestAddConstructorAsync("Class [|C|]\n End Class", """
                Class C
                    Shared Sub New()
                    End Sub
                End Class
                """,
                modifiers: new DeclarationModifiers(isStatic: true));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddChainedConstructor()
            => TestAddConstructorAsync("Class [|C|]\n Public Sub New(i As Integer)\n End Sub\n End Class", """
                Class C
                    Public Sub New()
                        Me.New(42)
                    End Sub
 
                    Public Sub New(i As Integer)
                 End Sub
                 End Class
                """,
                thisArguments: [VB.SyntaxFactory.ParseExpression("42")]);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544476")]
        public Task AddClass()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Class C
                    End Class
                End Namespace
                """);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddClassEscapeName()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Class [Class]
                    End Class
                End Namespace
                """,
                name: "Class");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddClassUnicodeName()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Class [Class]
                    End Class
                End Namespace
                """,
                name: "Class");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544477")]
        public Task AddNotInheritableClass()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public NotInheritable Class C
                    End Class
                End Namespace
                """,
                modifiers: new DeclarationModifiers(isSealed: true));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544477")]
        public Task AddMustInheritClass()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Friend MustInherit Class C
                    End Class
                End Namespace
                """,
                accessibility: Accessibility.Internal,
                modifiers: new DeclarationModifiers(isAbstract: true));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddStructure()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Friend Structure S
                    End Structure
                End Namespace
                """,
                name: "S",
                accessibility: Accessibility.Internal,
                typeKind: TypeKind.Struct);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546224")]
        public Task AddSealedStructure()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Structure S
                    End Structure
                End Namespace
                """,
                name: "S",
                accessibility: Accessibility.Public,
                modifiers: new DeclarationModifiers(isSealed: true),
                typeKind: TypeKind.Struct);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddInterface()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Interface I
                    End Interface
                End Namespace
                """,
                name: "I",
                typeKind: TypeKind.Interface);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544528")]
        public Task AddEnum()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Enum E
                        F1
                    End Enum
                End Namespace
                """, "E",
                typeKind: TypeKind.Enum,
                members: Members(CreateEnumField("F1", null)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544527")]
        public Task AddEnumWithValues()
            => TestAddNamedTypeAsync("Namespace [|N|]\n End Namespace", """
                Namespace N
                    Public Enum E
                        F1 = 1
                        F2 = 2
                    End Enum
                End Namespace
                """, "E",
                typeKind: TypeKind.Enum,
                members: Members(CreateEnumField("F1", 1), CreateEnumField("F2", 2)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddEnumMember()
            => TestAddFieldAsync("Public Enum [|E|]\n F1 = 1\n F2 = 2\n End Enum", """
                Public Enum E
                 F1 = 1
                 F2 = 2
                    F3
                End Enum
                """,
                name: "F3");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddEnumMemberWithValue()
            => TestAddFieldAsync("Public Enum [|E|]\n F1 = 1\n F2\n End Enum", """
                Public Enum E
                 F1 = 1
                 F2
                    F3 = 3
                End Enum
                """,
                name: "F3", hasConstantValue: true, constantValue: 3);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544529")]
        public Task AddDelegateType()
            => TestAddDelegateTypeAsync("Class [|C|]\n End Class", """
                Class C
                    Public Delegate Function D(s As String) As Integer
                End Class
                """,
                returnType: typeof(int),
                parameters: Parameters(Parameter(typeof(string), "s")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546224")]
        public Task AddSealedDelegateType()
            => TestAddDelegateTypeAsync("Class [|C|]\n End Class", """
                Class C
                    Public Delegate Function D(s As String) As Integer
                End Class
                """,
                returnType: typeof(int),
                modifiers: new DeclarationModifiers(isSealed: true),
                parameters: Parameters(Parameter(typeof(string), "s")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddEvent()
            => TestAddEventAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Event E As Action
                End Class
                """,
                context: new CodeGenerationContext(addImports: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddCustomEventToClassFromSourceSymbol()
        {
            var context = new CodeGenerationContext(reuseSyntax: true);
            await TestGenerateFromSourceSymbolAsync("""
                Public Class [|C2|]
                    Public Custom Event Click As EventHandler
                        AddHandler(ByVal value As EventHandler)
                            Events.AddHandler("ClickEvent", value)
                        End AddHandler
                        RemoveHandler(ByVal value As EventHandler)
                            Events.RemoveHandler("ClickEvent", value)
                        End RemoveHandler
                        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
                            CType(Events("ClickEvent"), EventHandler).Invoke(sender, e)
                        End RaiseEvent
                    End Event
                End Class
                """, "Class [|C1|]\nEnd Class", """
                Class C1
                    Public Custom Event Click As EventHandler
                        AddHandler(ByVal value As EventHandler)
                            Events.AddHandler("ClickEvent", value)
                        End AddHandler
                        RemoveHandler(ByVal value As EventHandler)
                            Events.RemoveHandler("ClickEvent", value)
                        End RemoveHandler
                        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
                            CType(Events("ClickEvent"), EventHandler).Invoke(sender, e)
                        End RaiseEvent
                    End Event
                End Class
                """, onlyGenerateMembers: true, context: context);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddEventWithAccessorAndImplementsClause()
        {
            static ImmutableArray<IEventSymbol> GetExplicitInterfaceEvent(SemanticModel semanticModel)
            {
                return [new CodeGenerationEventSymbol(
                        GetTypeSymbol(typeof(System.ComponentModel.INotifyPropertyChanged))(semanticModel),
                        attributes: default,
                        Accessibility.Public,
                        modifiers: default,
                        GetTypeSymbol(typeof(System.ComponentModel.PropertyChangedEventHandler))(semanticModel),
                        explicitInterfaceImplementations: default,
                        nameof(System.ComponentModel.INotifyPropertyChanged.PropertyChanged), null, null, null)];
            }
 
            await TestAddEventAsync("Class [|C|] \n End Class", """
                Class C
                    Public Custom Event E As ComponentModel.PropertyChangedEventHandler Implements ComponentModel.INotifyPropertyChanged.PropertyChanged
                        AddHandler(value As ComponentModel.PropertyChangedEventHandler)
                        End AddHandler
                        RemoveHandler(value As ComponentModel.PropertyChangedEventHandler)
                        End RemoveHandler
                        RaiseEvent(sender As Object, e As ComponentModel.PropertyChangedEventArgs)
                        End RaiseEvent
                    End Event
                End Class
                """,
                addMethod: CodeGenerationSymbolFactory.CreateAccessorSymbol(
                    [], Accessibility.NotApplicable, []),
                    getExplicitInterfaceImplementations: GetExplicitInterfaceEvent,
                    type: typeof(System.ComponentModel.PropertyChangedEventHandler),
                    context: new CodeGenerationContext(addImports: false));
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddEventWithAddAccessor()
            => TestAddEventAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Custom Event E As Action
                        AddHandler(value As Action)
                        End AddHandler
                        RemoveHandler(value As Action)
                        End RemoveHandler
                        RaiseEvent()
                        End RaiseEvent
                    End Event
                End Class
                """,
                addMethod: CodeGenerationSymbolFactory.CreateAccessorSymbol([], Accessibility.NotApplicable, []),
                context: new CodeGenerationContext(addImports: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddEventWithAccessors()
        {
            var addStatements = ImmutableArray.Create<SyntaxNode>(VB.SyntaxFactory.ParseExecutableStatement("Console.WriteLine(0)"));
            var removeStatements = ImmutableArray.Create<SyntaxNode>(VB.SyntaxFactory.ParseExecutableStatement("Console.WriteLine(1)"));
            var raiseStatements = ImmutableArray.Create<SyntaxNode>(VB.SyntaxFactory.ParseExecutableStatement("Console.WriteLine(2)"));
            await TestAddEventAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Custom Event E As Action
                        AddHandler(value As Action)
                            Console.WriteLine(0)
                        End AddHandler
                        RemoveHandler(value As Action)
                            Console.WriteLine(1)
                        End RemoveHandler
                        RaiseEvent()
                            Console.WriteLine(2)
                        End RaiseEvent
                    End Event
                End Class
                """,
                addMethod: CodeGenerationSymbolFactory.CreateAccessorSymbol(
                    [], Accessibility.NotApplicable, addStatements),
                removeMethod: CodeGenerationSymbolFactory.CreateAccessorSymbol(
                    [], Accessibility.NotApplicable, removeStatements),
                raiseMethod: CodeGenerationSymbolFactory.CreateAccessorSymbol(
                    [], Accessibility.NotApplicable, raiseStatements),
                context: new CodeGenerationContext(addImports: false));
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddMethodToClass()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Public Sub M()
                    End Sub
                End Class
                """,
                returnType: typeof(void));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddMethodToClassFromSourceSymbol()
        {
            var context = new CodeGenerationContext(reuseSyntax: true);
            await TestGenerateFromSourceSymbolAsync("""
                Public Class [|C2|]
                    Public Function FInt() As Integer
                        Return 0
                    End Function
                End Class
                """, "Class [|C1|]\nEnd Class", """
                Class C1
                    Public Function FInt() As Integer
                        Return 0
                    End Function
                End Class
                """, onlyGenerateMembers: true, context: context);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddMethodToClassEscapedName()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Protected Friend Sub [Sub]()
                    End Sub
                End Class
                """,
                accessibility: Accessibility.ProtectedOrInternal,
                name: "Sub",
                returnType: typeof(void));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544477")]
        public Task AddSharedMethodToStructure()
            => TestAddMethodAsync("Structure [|S|]\n End Structure", """
                Structure S
                    Public Shared Function M() As Integer
                        Return 0
                    End Function
                End Structure
                """,
                modifiers: new DeclarationModifiers(isStatic: true),
                returnType: typeof(int),
                statements: "Return 0");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddNotOverridableOverridesMethod()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Public NotOverridable Overrides Function GetHashCode() As Integer
                        $$
                    End Function
                End Class
                """,
                name: "GetHashCode",
                modifiers: new DeclarationModifiers(isOverride: true, isSealed: true),
                returnType: typeof(int),
                statements: "Return 0");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddMustOverrideMethod()
            => TestAddMethodAsync("MustInherit Class [|C|]\n End Class", "MustInherit Class C\n    Public MustOverride Sub M()\nEnd Class",
                modifiers: new DeclarationModifiers(isAbstract: true),
                returnType: typeof(void));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddMethodWithoutBody()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Public Sub M()
                End Class
                """,
                returnType: typeof(void),
                context: new CodeGenerationContext(generateMethodBodies: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddGenericMethod()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Public Function M(Of T)() As Integer
                        $$
                    End Function
                End Class
                """,
                returnType: typeof(int),
                typeParameters: [CodeGenerationSymbolFactory.CreateTypeParameterSymbol("T")],
                statements: "Return new T().GetHashCode()");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddVirtualMethod()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Protected Overridable Function M() As Integer
                        $$
                    End Function
                End Class
                """,
                accessibility: Accessibility.Protected,
                modifiers: new DeclarationModifiers(isVirtual: true),
                returnType: typeof(int),
                statements: "Return 0");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddShadowsMethod()
            => TestAddMethodAsync("Class [|C|]\n End Class", """
                Class C
                    Public Shadows Function ToString() As String
                        $$
                    End Function
                End Class
                """,
                name: "ToString",
                accessibility: Accessibility.Public,
                modifiers: new DeclarationModifiers(isNew: true),
                returnType: typeof(string),
                statements: "Return String.Empty");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddExplicitImplementation()
        {
            var input = "Interface I\n Sub M(i As Integer)\n End Interface\n Class [|C|]\n Implements I\n End Class";
            await TestAddMethodAsync(input, """
                Interface I
                 Sub M(i As Integer)
                 End Interface
                 Class C
                 Implements I
 
                    Public Sub M(i As Integer) Implements I.M
                    End Sub
                End Class
                """,
                name: "M",
                returnType: typeof(void),
                parameters: Parameters(Parameter(typeof(int), "i")),
                getExplicitInterfaces: s => [.. s.LookupSymbols(input.IndexOf('M'), null, "M").OfType<IMethodSymbol>()]);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddTrueFalseOperators()
            => TestAddOperatorsAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Shared Operator IsTrue(other As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator IsFalse(other As C) As Boolean
                        $$
                    End Operator
                End Class
                """,
                [CodeGenerationOperatorKind.True, CodeGenerationOperatorKind.False],
                parameters: Parameters(Parameter("C", "other")),
                returnType: typeof(bool),
                statements: "Return False");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddUnaryOperators()
            => TestAddOperatorsAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Shared Operator +(other As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator -(other As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator Not(other As C) As Object
                        $$
                    End Operator
                End Class
                """,
                [
                    CodeGenerationOperatorKind.UnaryPlus,
                    CodeGenerationOperatorKind.UnaryNegation,
                    CodeGenerationOperatorKind.LogicalNot
                ],
                parameters: Parameters(Parameter("C", "other")),
                returnType: typeof(object),
                statements: "Return Nothing");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddBinaryOperators()
            => TestAddOperatorsAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Shared Operator +(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator -(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator *(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator /(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator \(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator ^(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator &(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator Like(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator Mod(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator And(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator Or(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator Xor(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator <<(a As C, b As C) As Object
                        $$
                    End Operator
 
                    Public Shared Operator >>(a As C, b As C) As Object
                        $$
                    End Operator
                End Class
                """,
                [
                    CodeGenerationOperatorKind.Addition,
                    CodeGenerationOperatorKind.Subtraction,
                    CodeGenerationOperatorKind.Multiplication,
                    CodeGenerationOperatorKind.Division,
                    CodeGenerationOperatorKind.IntegerDivision,
                    CodeGenerationOperatorKind.Exponent,
                    CodeGenerationOperatorKind.Concatenate,
                    CodeGenerationOperatorKind.Like,
                    CodeGenerationOperatorKind.Modulus,
                    CodeGenerationOperatorKind.BitwiseAnd,
                    CodeGenerationOperatorKind.BitwiseOr,
                    CodeGenerationOperatorKind.ExclusiveOr,
                    CodeGenerationOperatorKind.LeftShift,
                    CodeGenerationOperatorKind.RightShift
                ],
                parameters: Parameters(Parameter("C", "a"), Parameter("C", "b")),
                returnType: typeof(object),
                statements: "Return Nothing");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddComparisonOperators()
            => TestAddOperatorsAsync("""
                Class [|C|]
                End Class
                """, """
                Class C
                    Public Shared Operator =(a As C, b As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator <>(a As C, b As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator >(a As C, b As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator <(a As C, b As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator >=(a As C, b As C) As Boolean
                        $$
                    End Operator
 
                    Public Shared Operator <=(a As C, b As C) As Boolean
                        $$
                    End Operator
                End Class
                """,
                [
                    CodeGenerationOperatorKind.Equality,
                    CodeGenerationOperatorKind.Inequality,
                    CodeGenerationOperatorKind.GreaterThan,
                    CodeGenerationOperatorKind.LessThan,
                    CodeGenerationOperatorKind.GreaterThanOrEqual,
                    CodeGenerationOperatorKind.LessThanOrEqual
                ],
                parameters: Parameters(Parameter("C", "a"), Parameter("C", "b")),
                returnType: typeof(bool),
                statements: "Return True");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddUnsupportedOperator()
            => TestAddUnsupportedOperatorAsync("Class [|C|]\n End Class",
                operatorKind: CodeGenerationOperatorKind.Increment,
                parameters: Parameters(Parameter("C", "other")),
                returnType: typeof(bool),
                statements: "Return True");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddExplicitConversion()
            => TestAddConversionAsync("Class [|C|]\n End Class", """
                Class C
                    Public Shared Narrowing Operator CType(other As C) As Integer
                        $$
                    End Operator
                End Class
                """,
                toType: typeof(int),
                fromType: Parameter("C", "other"),
                statements: "Return 0");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddImplicitConversion()
            => TestAddConversionAsync("Class [|C|]\n End Class", """
                Class C
                    Public Shared Widening Operator CType(other As C) As Integer
                        $$
                    End Operator
                End Class
                """,
                toType: typeof(int),
                fromType: Parameter("C", "other"),
                isImplicit: true,
                statements: "Return 0");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddStatementsToSub()
            => TestAddStatementsAsync("Class C\n [|Public Sub M\n Console.WriteLine(1)\n End Sub|]\n End Class", """
                Class C
                 Public Sub M
                 Console.WriteLine(1)
                $$ End Sub
                 End Class
                """, "Console.WriteLine(2)");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddStatementsToOperator()
            => TestAddStatementsAsync("Class C\n [|Shared Operator +(arg As C) As C\n Return arg\n End Operator|]\n End Class", """
                Class C
                 Shared Operator +(arg As C) As C
                 Return arg
                $$ End Operator
                 End Class
                """, "Return Nothing");
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddStatementsToPropertySetter()
            => TestAddStatementsAsync("Imports System\n Class C\n WriteOnly Property P As String\n [|Set\n End Set|]\n End Property\n End Class", """
                Imports System
                 Class C
                 WriteOnly Property P As String
                 Set
                $$ End Set
                 End Property
                 End Class
                """, """
                Console.WriteLine("Setting the value"
                """);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddParametersToMethod()
            => TestAddParametersAsync("Class C\n Public [|Sub M()\n End Sub|]\n End Class", """
                Class C
                 Public Sub M(numAs Integer, OptionaltextAs String = "Hello!",OptionalfloatingAs Single = 0.5)
                 End Sub
                 End Class
                """,
                Parameters(Parameter(typeof(int), "num"), Parameter(typeof(string), "text", true, "Hello!"), Parameter(typeof(float), "floating", true, .5F)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844460")]
        public Task AddParametersToPropertyBlock()
            => TestAddParametersAsync("Class C\n [|Public Property P As String\n Get\n Return String.Empty\n End Get\n Set(value As String)\n End Set\n End Property|]\n End Class", """
                Class C
                 Public Property P (numAs Integer) As String
                 Get
                 Return String.Empty
                 End Get
                 Set(value As String)
                 End Set
                 End Property
                 End Class
                """,
                Parameters(Parameter(typeof(int), "num")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844460")]
        public Task AddParametersToPropertyStatement()
            => TestAddParametersAsync("Class C\n [|Public Property P As String|]\n Get\n Return String.Empty\n End Get\n Set(value As String)\n End Set\n End Property\n End Class", """
                Class C
                 Public Property P (numAs Integer) As String
                 Get
                 Return String.Empty
                 End Get
                 Set(value As String)
                 End Set
                 End Property
                 End Class
                """,
                Parameters(Parameter(typeof(int), "num")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844460")]
        public Task AddParametersToPropertyGetter_ShouldNotSucceed()
            => TestAddParametersAsync("Class C\n Public Property P As String\n [|Get\n Return String.Empty\n End Get|]\n Set(value As String)\n End Set\n End Property\n End Class", "Class C\n Public Property P As String\n Get\n Return String.Empty\n End Get\n Set(value As String)\n End Set\n End Property\n End Class",
                Parameters(Parameter(typeof(int), "num")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/844460")]
        public Task AddParametersToPropertySetter_ShouldNotSucceed()
            => TestAddParametersAsync("Class C\n Public Property P As String\n Get\n Return String.Empty\n End Get\n [|Set(value As String)\n End Set|]\n End Property\n End Class", "Class C\n Public Property P As String\n Get\n Return String.Empty\n End Get\n Set(value As String)\n End Set\n End Property\n End Class",
                Parameters(Parameter(typeof(int), "num")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddParametersToOperator()
            => TestAddParametersAsync("Class C\n [|Shared Operator +(a As C) As C\n Return a\n End Operator|]\n End Class", """
                Class C
                 Shared Operator +(a As C,bAs C) As C
                 Return a
                 End Operator
                 End Class
                """,
                Parameters(Parameter("C", "b")));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAutoProperty()
            => TestAddPropertyAsync("Class [|C|]\n End Class", """
                Class C
                    Public Property P As Integer
                End Class
                """,
                type: typeof(int));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task AddPropertyToClassFromSourceSymbol()
        {
            var context = new CodeGenerationContext(reuseSyntax: true);
            await TestGenerateFromSourceSymbolAsync("""
                Public Class [|C2|]
                    Public Property P As Integer
                        Get
                            Return 0
                        End Get
                    End Property
                End Class
                """, "Class [|C1|]\nEnd Class", """
                Class C1
                    Public Property P As Integer
                        Get
                            Return 0
                        End Get
                    End Property
                End Class
                """, onlyGenerateMembers: true, context: context);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddPropertyWithoutAccessorBodies()
            => TestAddPropertyAsync("Class [|C|]\n End Class", """
                Class C
                    Public Property P As Integer
                End Class
                """,
                type: typeof(int),
                getStatements: "Return 0",
                setStatements: "Me.P = Value",
                context: new CodeGenerationContext(generateMethodBodies: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddIndexer()
            => TestAddPropertyAsync("Class [|C|]\n End Class", """
                Class C
                    Default Public ReadOnly Property Item(i As Integer) As String
                        Get
                            $$
                        End Get
                    End Property
                End Class
                """,
                name: "Item",
                type: typeof(string),
                parameters: Parameters(Parameter(typeof(int), "i")),
                getStatements: "Return String.Empty",
                isIndexer: true);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToTypes()
            => TestAddAttributeAsync("Class [|C|]\n End Class", """
                <Serializable>
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromTypes()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                <Serializable>
                Class [|C|]
                End Class
                """, """
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToMethods()
            => TestAddAttributeAsync("Class C\n Public Sub [|M()|] \n End Sub \n End Class", """
                Class C
                    <Serializable>
                    Public Sub M()
                    End Sub 
                 End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromMethods()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Class C
                    <Serializable>
                    Public Sub [|M()|]
                    End Sub
                End Class
                """, """
                Class C
                    Public Sub M()
                    End Sub
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToFields()
            => TestAddAttributeAsync("Class C\n [|Public F As Integer|]\n End Class", """
                Class C
                    <Serializable>
                    Public F As Integer
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromFields()
            => TestRemoveAttributeAsync<FieldDeclarationSyntax>("""
                Class C
                    <Serializable>
                    Public [|F|] As Integer
                End Class
                """, """
                Class C
                    Public F As Integer
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToProperties()
            => TestAddAttributeAsync("Class C \n Public Property [|P|] As Integer \n End Class", """
                Class C
                    <Serializable>
                    Public Property P As Integer
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromProperties()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Class C
                    <Serializable>
                    Public Property [|P|] As Integer
                End Class
                """, """
                Class C
                    Public Property P As Integer
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToPropertyAccessor()
            => TestAddAttributeAsync("Class C \n Public ReadOnly Property P As Integer \n [|Get|] \n Return 10 \n End Get \n End Property \n  End Class", """
                Class C 
                 Public ReadOnly Property P As Integer
                        <Serializable>
                        Get
                            Return 10 
                 End Get 
                 End Property 
                  End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromPropertyAccessor()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Class C
                    Public Property P As Integer
                        <Serializable>
                        [|Get|]
                            Return 10
                        End Get
                End Class
                """, """
                Class C
                    Public Property P As Integer
                        Get
                            Return 10
                        End Get
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToEnums()
            => TestAddAttributeAsync("Module M \n [|Enum C|] \n One \n Two \n End Enum\n End Module", """
                Module M
                    <Serializable>
                    Enum C
                        One 
                 Two 
                 End Enum
                 End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromEnums()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Module M
                    <Serializable>
                    Enum [|C|]
                        One
                        Two
                    End Enum
                End Module
                """, """
                Module M
                    Enum C
                        One
                        Two
                    End Enum
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToEnumMembers()
            => TestAddAttributeAsync("Module M \n Enum C \n [|One|] \n Two \n End Enum\n End Module", """
                Module M 
                 Enum C
                        <Serializable>
                        One
                        Two 
                 End Enum
                 End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromEnumMembers()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Module M
                    Enum C
                        <Serializable>
                        [|One|]
                        Two
                    End Enum
                End Module
                """, """
                Module M
                    Enum C
                        One
                        Two
                    End Enum
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToModule()
            => TestAddAttributeAsync("Module [|M|] \n End Module", """
                <Serializable>
                Module M
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromModule()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                <Serializable>
                Module [|M|]
                End Module
                """, """
                Module M
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToOperator()
            => TestAddAttributeAsync("Class C \n Public Shared Operator [|+|] (x As C, y As C) As C \n Return New C() \n End Operator \n End Class", """
                Class C
                    <Serializable>
                    Public Shared Operator +(x As C, y As C) As C
                        Return New C() 
                 End Operator 
                 End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromOperator()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Module M
                    Class C
                        <Serializable>
                        Public Shared Operator [|+|](x As C, y As C) As C
                            Return New C()
                        End Operator
                    End Class
                End Module
                """, """
                Module M
                    Class C
                        Public Shared Operator +(x As C, y As C) As C
                            Return New C()
                        End Operator
                    End Class
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToDelegate()
            => TestAddAttributeAsync("Module M \n Delegate Sub [|D()|]\n End Module", "Module M\n    <Serializable>\n    Delegate Sub D()\nEnd Module", typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromDelegate()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Module M
                    <Serializable>
                    Delegate Sub [|D()|]
                End Module
                """, """
                Module M
                    Delegate Sub D()
                End Module
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToParam()
            => TestAddAttributeAsync("Class C \n Public Sub M([|x As Integer|]) \n End Sub \n End Class", "Class C \n Public Sub M(<Serializable> x As Integer) \n End Sub \n End Class", typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeFromParam()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                Class C
                    Public Sub M(<Serializable> [|x As Integer|])
                    End Sub
                End Class
                """, """
                Class C
                    Public Sub M(x As Integer)
                    End Sub
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeToCompilationUnit()
            => TestAddAttributeAsync("[|Class C \n End Class \n Class D \n End Class|]", "<Assembly: Serializable>\nClass C\nEnd Class\nClass D\nEnd Class", typeof(SerializableAttribute), VB.SyntaxFactory.Token(VB.SyntaxKind.AssemblyKeyword));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task AddAttributeWithWrongTarget()
            => Assert.ThrowsAsync<AggregateException>(async () =>
                await TestAddAttributeAsync("[|Class C \n End Class \n Class D \n End Class|]", "<Assembly: Serializable> Class C \n End Class \n Class D \n End Class", typeof(SerializableAttribute), VB.SyntaxFactory.Token(VB.SyntaxKind.ReturnKeyword)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeWithTrivia()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                ' Comment 1
                <System.Serializable> ' Comment 2
                Class [|C|]
                End Class
                """, """
                ' Comment 1
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeWithTrivia_NewLine()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                ' Comment 1
                <System.Serializable>
                Class [|C|]
                End Class
                """, """
                ' Comment 1
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeWithMultipleAttributes()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                ' Comment 1
                <  System.Serializable   ,  System.Flags> ' Comment 2
                Class [|C|]
                End Class
                """, """
                ' Comment 1
                <System.Flags> ' Comment 2
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task RemoveAttributeWithMultipleAttributeLists()
            => TestRemoveAttributeAsync<SyntaxNode>("""
                ' Comment 1
                <  System.Serializable   ,  System.Flags> ' Comment 2
                <System.Obsolete> ' Comment 3
                Class [|C|]
                End Class
                """, """
                ' Comment 1
                <System.Flags> ' Comment 2
                <System.Obsolete> ' Comment 3
                Class C
                End Class
                """, typeof(SerializableAttribute));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task TestUpdateModifiers()
        {
            var eol = VB.SyntaxFactory.EndOfLine(@"");
            var newModifiers = new[] { VB.SyntaxFactory.Token(VB.SyntaxKind.FriendKeyword).WithLeadingTrivia(eol) }.Concat(
                CreateModifierTokens(new DeclarationModifiers(isSealed: true, isPartial: true), LanguageNames.VisualBasic));
 
            await TestUpdateDeclarationAsync<ClassStatementSyntax>("""
                Public Shared Class [|C|] ' Comment 1
                    ' Comment 2
                End Class
                """, """
                Friend Partial NotInheritable Class C ' Comment 1
                    ' Comment 2
                End Class
                """, modifiers: newModifiers);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task TestUpdateAccessibility()
            => TestUpdateDeclarationAsync<ClassStatementSyntax>("""
                ' Comment 0
                Public Shared Class [|C|] ' Comment 1
                    ' Comment 2
                End Class
                """, """
                ' Comment 0
                Protected Friend Shared Class C ' Comment 1
                    ' Comment 2
                End Class
                """, accessibility: Accessibility.ProtectedOrFriend);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public Task TestUpdateDeclarationType()
            => TestUpdateDeclarationAsync<MethodStatementSyntax>("""
                Public Shared Class C
                    ' Comment 1
                    Public Shared Function [|F|]() As Char
                        Return 0
                    End Function
                End Class
                """, """
                Public Shared Class C
                    ' Comment 1
                    Public Shared Function F() As Integer
                        Return 0
                    End Function
                End Class
                """, getType: GetTypeSymbol(typeof(int)));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        public async Task TestUpdateDeclarationMembers()
        {
            var getField = CreateField(Accessibility.Public, new DeclarationModifiers(isStatic: true), typeof(int), "f2");
            var getMembers = ImmutableArray.Create(getField);
            await TestUpdateDeclarationAsync<ClassBlockSyntax>("""
                Public Shared Class [|C|]
                    ' Comment 0
                    Public Shared {|RetainedMember:f|} As Integer
 
                    ' Comment 1
                    Public Shared Function F() As Char
                        Return 0
                    End Function
                End Class
                """, """
                Public Shared Class C
                    ' Comment 0
                    Public Shared f As Integer
                    Public Shared f2 As Integer
                End Class
                """, getNewMembers: getMembers);
        }
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGenerationSortDeclarations)]
        public Task SortModules()
            => TestGenerateFromSourceSymbolAsync("Public Class [|C|] \n End Class", "Namespace [|N|] \n Module M \n End Module \n End Namespace", """
                Namespace N
                    Public Class C
                    End Class
 
                    Module M 
                 End Module 
                 End Namespace
                """);
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGenerationSortDeclarations)]
        public Task SortOperators()
            => TestGenerateFromSourceSymbolAsync("""
                Namespace N
                    Public Class [|C|]
                        ' Unary operators
                        Public Shared Operator IsFalse(other As C) As Boolean
                            Return False
                        End Operator
                        Public Shared Operator IsTrue(other As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator Not(other As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator -(other As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator + (other As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Narrowing Operator CType(c As C) As Integer
                            Return 0
                        End Operator
 
                        ' Binary operators
                        Public Shared Operator >= (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator <= (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator > (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator < (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator <> (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator = (a As C, b As C) As Boolean
                            Return True
                        End Operator
                        Public Shared Operator >> (a As C, shift As Integer) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator << (a As C, shift As Integer) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator Xor(a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator Or(a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator And(a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator Mod(a As C, b As C) As C
                            Return Nothing
                        End Operator
                          Public Shared Operator Like (a As C, b As C) As C
                            Return Nothing
                        End Operator
                          Public Shared Operator & (a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator ^ (a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator \ (a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator / (a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator *(a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator -(a As C, b As C) As C
                            Return Nothing
                        End Operator
                        Public Shared Operator + (a As C, b As C) As C
                            Return Nothing
                        End Operator
                    End Class
                End Namespace
                """, "Namespace [|N|] \n End Namespace", """
                Namespace N
                    Public Class C
                        Public Shared Operator +(other As C) As C
                        Public Shared Operator +(a As C, b As C) As C
                        Public Shared Operator -(other As C) As C
                        Public Shared Operator -(a As C, b As C) As C
                        Public Shared Operator *(a As C, b As C) As C
                        Public Shared Operator /(a As C, b As C) As C
                        Public Shared Operator \(a As C, b As C) As C
                        Public Shared Operator ^(a As C, b As C) As C
                        Public Shared Operator &(a As C, b As C) As C
                        Public Shared Operator Not(other As C) As C
                        Public Shared Operator Like(a As C, b As C) As C
                        Public Shared Operator Mod(a As C, b As C) As C
                        Public Shared Operator And(a As C, b As C) As C
                        Public Shared Operator Or(a As C, b As C) As C
                        Public Shared Operator Xor(a As C, b As C) As C
                        Public Shared Operator <<(a As C, shift As Integer) As C
                        Public Shared Operator >>(a As C, shift As Integer) As C
                        Public Shared Operator =(a As C, b As C) As Boolean
                        Public Shared Operator <>(a As C, b As C) As Boolean
                        Public Shared Operator >(a As C, b As C) As Boolean
                        Public Shared Operator <(a As C, b As C) As Boolean
                        Public Shared Operator >=(a As C, b As C) As Boolean
                        Public Shared Operator <=(a As C, b As C) As Boolean
                        Public Shared Operator IsTrue(other As C) As Boolean
                        Public Shared Operator IsFalse(other As C) As Boolean
                        Public Shared Narrowing Operator CType(c As C) As Integer
                    End Class
                End Namespace
                """,
                forceLanguage: LanguageNames.VisualBasic,
                context: new CodeGenerationContext(generateMethodBodies: false));
 
        [Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
        [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/848357")]
        public Task TestConstraints()
            => TestGenerateFromSourceSymbolAsync("""
                Namespace N
                    Public Class [|C|](Of T As Structure, U As Class)
                        Public Sub Goo(Of Q As New, R As IComparable)()
                        End Sub
                        Public Delegate Sub D(Of T1 As Structure, T2 As Class)(t As T1, u As T2)
                    End Class
                End Namespace
                """, "Namespace [|N|] \n End Namespace", """
                Namespace N
                    Public Class C(Of T As Structure, U As Class)
                        Public Sub Goo(Of Q As New, R As IComparable)()
                        Public Delegate Sub D(Of T1 As Structure, T2 As Class)(t As T1, u As T2)
                    End Class
                End Namespace
                """,
                context: new CodeGenerationContext(generateMethodBodies: false),
                onlyGenerateMembers: true);
    }
}