File: CodeModel\AbstractCodeModelObject_CodeGen.cs
Web Access
Project: src\src\VisualStudio\Core\Impl\Microsoft.VisualStudio.LanguageServices.Implementation.csproj (Microsoft.VisualStudio.LanguageServices.Implementation)
// 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.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeGeneration;
using Microsoft.CodeAnalysis.Editing;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.CodeModel;
 
/// <summary>
/// This is the root class for all code model objects. It contains methods that
/// are common to everything.
/// </summary>
public partial class AbstractCodeModelObject
{
    private CodeGenerationContextInfo GetCodeGenerationContextInfo(
        SyntaxNode containerNode,
        CodeGenerationOptions options,
        EnvDTE.vsCMAccess access = EnvDTE.vsCMAccess.vsCMAccessDefault,
        bool generateMethodBodies = true)
    {
        var generateDefaultAccessibility = (access & EnvDTE.vsCMAccess.vsCMAccessDefault) == 0;
 
        return CodeGenerationService.GetInfo(
            new CodeGenerationContext(
                generateDefaultAccessibility: generateDefaultAccessibility,
                generateMethodBodies: generateMethodBodies),
            options,
            containerNode.SyntaxTree.Options);
    }
 
    private protected SyntaxNode CreateConstructorDeclaration(SyntaxNode containerNode, string typeName, EnvDTE.vsCMAccess access, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newMethodSymbol = CodeGenerationSymbolFactory.CreateConstructorSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Method, destination),
            modifiers: new DeclarationModifiers(),
            typeName: typeName,
            parameters: default);
 
        var info = GetCodeGenerationContextInfo(containerNode, options, access: access);
        var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None);
        Contract.ThrowIfNull(method);
        return method;
    }
 
    private protected SyntaxNode CreateDestructorDeclaration(SyntaxNode containerNode, string typeName, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newMethodSymbol = CodeGenerationSymbolFactory.CreateDestructorSymbol(
            attributes: default,
            typeName: typeName);
 
        var info = GetCodeGenerationContextInfo(containerNode, options);
        var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None);
        Contract.ThrowIfNull(method);
        return method;
    }
 
    private protected SyntaxNode CreateDelegateTypeDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, INamedTypeSymbol returnType, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newTypeSymbol = CodeGenerationSymbolFactory.CreateDelegateTypeSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.NamedType, destination),
            modifiers: new DeclarationModifiers(),
            returnType: returnType,
            refKind: RefKind.None,
            name: name);
 
        var info = GetCodeGenerationContextInfo(containerNode, options, access: access);
 
        return CodeGenerationService.CreateNamedTypeDeclaration(newTypeSymbol, destination, info, CancellationToken.None);
    }
 
    private protected SyntaxNode CreateEventDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, CodeGenerationOptions options, bool createPropertyStyleEvent)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        IMethodSymbol? addMethod = null;
        IMethodSymbol? removeMethod = null;
 
        if (createPropertyStyleEvent)
        {
            addMethod = CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes: default,
                accessibility: Accessibility.NotApplicable,
                modifiers: new DeclarationModifiers(),
                returnType: null,
                refKind: RefKind.None,
                explicitInterfaceImplementations: default,
                name: "add_" + name,
                typeParameters: default,
                parameters: default);
 
            removeMethod = CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes: default,
                accessibility: Accessibility.NotApplicable,
                modifiers: new DeclarationModifiers(),
                returnType: null,
                refKind: RefKind.None,
                explicitInterfaceImplementations: default,
                name: "remove_" + name,
                typeParameters: default,
                parameters: default);
        }
 
        var newEventSymbol = CodeGenerationSymbolFactory.CreateEventSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Event, destination),
            modifiers: new DeclarationModifiers(),
            type: type,
            explicitInterfaceImplementations: default,
            name: name,
            addMethod: addMethod,
            removeMethod: removeMethod);
 
        var info = GetCodeGenerationContextInfo(containerNode, options, access: access);
        return CodeGenerationService.CreateEventDeclaration(newEventSymbol, destination, info, CancellationToken.None);
    }
 
    private protected SyntaxNode CreateFieldDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol type, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newFieldSymbol = CodeGenerationSymbolFactory.CreateFieldSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Field, destination),
            modifiers: new DeclarationModifiers(isWithEvents: CodeModelService.GetWithEvents(access)),
            type: type,
            name: name);
 
        var info = GetCodeGenerationContextInfo(containerNode, options, access: access);
        return CodeGenerationService.CreateFieldDeclaration(newFieldSymbol, destination, info, CancellationToken.None);
    }
 
    private protected SyntaxNode CreateMethodDeclaration(SyntaxNode containerNode, string name, EnvDTE.vsCMAccess access, ITypeSymbol returnType, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newMethodSymbol = CodeGenerationSymbolFactory.CreateMethodSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Method, destination),
            modifiers: new DeclarationModifiers(),
            returnType: returnType,
            refKind: RefKind.None,
            explicitInterfaceImplementations: default,
            name: name,
            typeParameters: default,
            parameters: default);
 
        // Generating method with body is allowed when targeting an interface,
        // so we have to explicitly disable it here.
        var info = GetCodeGenerationContextInfo(
            containerNode,
            options,
            access: access,
            generateMethodBodies: destination != CodeGenerationDestination.InterfaceType);
 
        var method = CodeGenerationService.CreateMethodDeclaration(newMethodSymbol, destination, info, CancellationToken.None);
        Contract.ThrowIfNull(method);
        return method;
    }
 
    private protected SyntaxNode CreatePropertyDeclaration(
        SyntaxNode containerNode,
        string name,
        bool generateGetter,
        bool generateSetter,
        EnvDTE.vsCMAccess access,
        ITypeSymbol type,
        CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        IMethodSymbol? getMethod = null;
        if (generateGetter)
        {
            getMethod = CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes: default,
                accessibility: Accessibility.NotApplicable,
                modifiers: new DeclarationModifiers(),
                returnType: null,
                refKind: RefKind.None,
                explicitInterfaceImplementations: default,
                name: "get_" + name,
                typeParameters: default,
                parameters: default,
                statements: [CodeModelService.CreateReturnDefaultValueStatement(type)]);
        }
 
        IMethodSymbol? setMethod = null;
        if (generateSetter)
        {
            setMethod = CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes: default,
                accessibility: Accessibility.NotApplicable,
                modifiers: new DeclarationModifiers(),
                returnType: null,
                refKind: RefKind.None,
                explicitInterfaceImplementations: default,
                name: "set_" + name,
                typeParameters: default,
                parameters: default);
        }
 
        var newPropertySymbol = CodeGenerationSymbolFactory.CreatePropertySymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.Field, destination),
            modifiers: new DeclarationModifiers(),
            type: type,
            refKind: RefKind.None,
            explicitInterfaceImplementations: default,
            name: name,
            parameters: default,
            getMethod: getMethod,
            setMethod: setMethod);
 
        var info = GetCodeGenerationContextInfo(containerNode, options, access);
        return CodeGenerationService.CreatePropertyDeclaration(newPropertySymbol, destination, info, CancellationToken.None);
    }
 
    private protected SyntaxNode CreateNamespaceDeclaration(SyntaxNode containerNode, string name, CodeGenerationOptions options)
    {
        var destination = CodeModelService.GetDestination(containerNode);
        var newNamespaceSymbol = CodeGenerationSymbolFactory.CreateNamespaceSymbol(name);
 
        var info = GetCodeGenerationContextInfo(containerNode, options);
        return CodeGenerationService.CreateNamespaceDeclaration(newNamespaceSymbol, destination, info, CancellationToken.None);
    }
 
    private protected SyntaxNode CreateTypeDeclaration(
        SyntaxNode containerNode,
        TypeKind typeKind,
        string name,
        EnvDTE.vsCMAccess access,
        CodeGenerationOptions options,
        INamedTypeSymbol? baseType = null,
        ImmutableArray<INamedTypeSymbol> implementedInterfaces = default)
    {
        var destination = CodeModelService.GetDestination(containerNode);
 
        var newTypeSymbol = CodeGenerationSymbolFactory.CreateNamedTypeSymbol(
            attributes: default,
            accessibility: CodeModelService.GetAccessibility(access, SymbolKind.NamedType, destination),
            modifiers: new DeclarationModifiers(),
            typeKind: typeKind,
            name: name,
            typeParameters: default,
            baseType: baseType,
            interfaces: implementedInterfaces,
            specialType: SpecialType.None,
            members: default);
 
        var codeGenOptions = GetCodeGenerationContextInfo(containerNode, options, access: access);
        return CodeGenerationService.CreateNamedTypeDeclaration(newTypeSymbol, destination, codeGenOptions, CancellationToken.None);
    }
}