ConversionGenerator.cs 4.9 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2

3
using System;
P
Pilchie 已提交
4
using System.Collections.Generic;
5
using System.Threading;
P
Pilchie 已提交
6
using Microsoft.CodeAnalysis.CodeGeneration;
7
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
P
Pilchie 已提交
8 9 10
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;

V
VSadov 已提交
11 12 13
using static Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationHelpers;
using static Microsoft.CodeAnalysis.CSharp.CodeGeneration.CSharpCodeGenerationHelpers;

P
Pilchie 已提交
14 15
namespace Microsoft.CodeAnalysis.CSharp.CodeGeneration
{
16
    internal static class ConversionGenerator
P
Pilchie 已提交
17 18 19 20
    {
        internal static TypeDeclarationSyntax AddConversionTo(
            TypeDeclarationSyntax destination,
            IMethodSymbol method,
21
            Workspace workspace,
P
Pilchie 已提交
22 23 24
            CodeGenerationOptions options,
            IList<bool> availableIndices)
        {
25
            var methodDeclaration = GenerateConversionDeclaration(
26 27
                method, GetDestination(destination), workspace, options,
                destination?.SyntaxTree.Options ?? options.ParseOptions);
P
Pilchie 已提交
28 29 30 31 32 33

            var members = Insert(destination.Members, methodDeclaration, options, availableIndices, after: LastOperator);

            return AddMembersTo(destination, members);
        }

34
        internal static ConversionOperatorDeclarationSyntax GenerateConversionDeclaration(
P
Pilchie 已提交
35 36
            IMethodSymbol method,
            CodeGenerationDestination destination,
37
            Workspace workspace,
38 39
            CodeGenerationOptions options,
            ParseOptions parseOptions)
P
Pilchie 已提交
40
        {
41
            var declaration = GenerateConversionDeclarationWorker(method, destination, workspace, options, parseOptions);
42 43
            return AddCleanupAnnotationsTo(AddAnnotationsTo(method,
                ConditionallyAddDocumentationCommentTo(declaration, method, options)));
P
Pilchie 已提交
44 45 46 47 48
        }

        private static ConversionOperatorDeclarationSyntax GenerateConversionDeclarationWorker(
            IMethodSymbol method,
            CodeGenerationDestination destination,
49
            Workspace workspace,
50 51
            CodeGenerationOptions options,
            ParseOptions parseOptions)
P
Pilchie 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65
        {
            var hasNoBody = !options.GenerateMethodBodies || method.IsExtern;

            var reusableSyntax = GetReuseableSyntaxNodeForSymbol<ConversionOperatorDeclarationSyntax>(method, options);
            if (reusableSyntax != null)
            {
                return reusableSyntax;
            }

            var operatorToken = SyntaxFactory.Token(SyntaxFacts.GetOperatorKind(method.MetadataName));
            var keyword = method.MetadataName == WellKnownMemberNames.ImplicitConversionName
                ? SyntaxFactory.Token(SyntaxKind.ImplicitKeyword)
                : SyntaxFactory.Token(SyntaxKind.ExplicitKeyword);

66
            var declaration = SyntaxFactory.ConversionOperatorDeclaration(
P
Pilchie 已提交
67 68 69 70 71 72 73 74
                attributeLists: AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options),
                modifiers: GenerateModifiers(method),
                implicitOrExplicitKeyword: keyword,
                operatorKeyword: SyntaxFactory.Token(SyntaxKind.OperatorKeyword),
                type: method.ReturnType.GenerateTypeSyntax(),
                parameterList: ParameterGenerator.GenerateParameterList(method.Parameters, isExplicit: false, options: options),
                body: hasNoBody ? null : StatementGenerator.GenerateBlock(method),
                semicolonToken: hasNoBody ? SyntaxFactory.Token(SyntaxKind.SemicolonToken) : new SyntaxToken());
75

76
            declaration = UseExpressionBodyIfDesired(workspace, declaration, parseOptions);
77 78 79 80 81

            return declaration;
        }

        private static ConversionOperatorDeclarationSyntax UseExpressionBodyIfDesired(
C
CyrusNajmabadi 已提交
82
            Workspace workspace, ConversionOperatorDeclarationSyntax declaration, ParseOptions options)
83 84 85
        {
            if (declaration.ExpressionBody == null)
            {
86 87 88
                var expressionBodyPreference = workspace.Options.GetOption(CSharpCodeStyleOptions.PreferExpressionBodiedOperators).Value;

                if (declaration.Body.TryConvertToExpressionBody(
89 90
                        declaration.Kind(), options, expressionBodyPreference,
                        out var expressionBody, out var semicolonToken))
91
                {
92 93 94
                    return declaration.WithBody(null)
                                      .WithExpressionBody(expressionBody)
                                      .WithSemicolonToken(semicolonToken);
95 96 97 98
                }
            }

            return declaration;
P
Pilchie 已提交
99 100 101 102 103 104 105 106 107
        }

        private static SyntaxTokenList GenerateModifiers(IMethodSymbol method)
        {
            return SyntaxFactory.TokenList(
                SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                SyntaxFactory.Token(SyntaxKind.StaticKeyword));
        }
    }
108
}