예제 #1
0
        public static bool TryConvertToArrowExpressionBody(
            this BlockSyntax block,
            SyntaxKind declarationKind,
            ParseOptions options,
            ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken
            )
        {
            var version = ((CSharpParseOptions)options).LanguageVersion;

            // We can always use arrow-expression bodies in C# 7 or above.
            // We can also use them in C# 6, but only a select set of member kinds.
            var acceptableVersion =
                version >= LanguageVersion.CSharp7 ||
                (version >= LanguageVersion.CSharp6 && IsSupportedInCSharp6(declarationKind));

            if (
                !acceptableVersion ||
                !block.TryConvertToExpressionBody(
                    options,
                    preference,
                    out var expression,
                    out semicolonToken
                    )
                )
            {
                arrowExpression = null;
                semicolonToken  = default;
                return(false);
            }

            arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);
            return(true);
        }
예제 #2
0
        public static bool TryConvertToExpressionBody(
            this BlockSyntax block, ParseOptions options,
            ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken)
        {
            if (preference != ExpressionBodyPreference.Never &&
                (options as CSharpParseOptions)?.LanguageVersion >= LanguageVersion.CSharp7)
            {
                if (block != null && block.Statements.Count == 1)
                {
                    var firstStatement = block.Statements[0];

                    if (TryGetExpression(firstStatement, out var expression, out semicolonToken) &&
                        MatchesPreference(expression, preference))
                    {
                        arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);

                        // The close brace of the block may have important trivia on it (like
                        // comments or directives).  Preserve them on the semicolon when we
                        // convert to an expression body.
                        semicolonToken = semicolonToken.WithAppendedTrailingTrivia(
                            block.CloseBraceToken.LeadingTrivia.Where(t => !t.IsWhitespaceOrEndOfLine()));
                        return(true);
                    }
                }
            }

            arrowExpression = null;
            semicolonToken  = default(SyntaxToken);
            return(false);
        }
 public CSharpCodeGenerationPreferences(
     bool placeSystemNamespaceFirst,
     ExpressionBodyPreference preferExpressionBodiedMethods,
     ExpressionBodyPreference preferExpressionBodiedAccessors,
     ExpressionBodyPreference preferExpressionBodiedProperties,
     ExpressionBodyPreference preferExpressionBodiedIndexers,
     ExpressionBodyPreference preferExpressionBodiedConstructors,
     ExpressionBodyPreference preferExpressionBodiedOperators,
     ExpressionBodyPreference preferExpressionBodiedLocalFunctions,
     NamespaceDeclarationPreference namespaceDeclarations,
     AddImportPlacement preferredUsingDirectivePlacement,
     LanguageVersion languageVersion)
     : base(placeSystemNamespaceFirst)
 {
     PreferExpressionBodiedMethods        = preferExpressionBodiedMethods;
     PreferExpressionBodiedAccessors      = preferExpressionBodiedAccessors;
     PreferExpressionBodiedProperties     = preferExpressionBodiedProperties;
     PreferExpressionBodiedIndexers       = preferExpressionBodiedIndexers;
     PreferExpressionBodiedConstructors   = preferExpressionBodiedConstructors;
     PreferExpressionBodiedOperators      = preferExpressionBodiedOperators;
     PreferExpressionBodiedLocalFunctions = preferExpressionBodiedLocalFunctions;
     NamespaceDeclarations            = namespaceDeclarations;
     PreferredUsingDirectivePlacement = preferredUsingDirectivePlacement;
     LanguageVersion = languageVersion;
 }
예제 #4
0
        private static bool TryGetExpressionBody(
            BasePropertyDeclarationSyntax baseProperty,
            ParseOptions options,
            ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken
            )
        {
            var accessorList = baseProperty.AccessorList;

            if (preference != ExpressionBodyPreference.Never && accessorList.Accessors.Count == 1)
            {
                var accessor = accessorList.Accessors[0];
                if (accessor.IsKind(SyntaxKind.GetAccessorDeclaration))
                {
                    return(TryGetArrowExpressionBody(
                               baseProperty.Kind(),
                               accessor,
                               options,
                               preference,
                               out arrowExpression,
                               out semicolonToken
                               ));
                }
            }

            arrowExpression = null;
            semicolonToken  = default;
            return(false);
        }
 private static SyntaxNode UseExpressionOrBlockBodyIfDesired(
     LanguageVersion languageVersion,
     MethodDeclarationSyntax methodDeclaration,
     ExpressionBodyPreference expressionBodyPreference,
     bool createReturnStatementForExpression)
 {
     if (methodDeclaration.Body != null && expressionBodyPreference != ExpressionBodyPreference.Never)
     {
         if (methodDeclaration.Body.TryConvertToArrowExpressionBody(
                 methodDeclaration.Kind(), languageVersion, expressionBodyPreference,
                 out var arrowExpression, out var semicolonToken))
         {
             return(methodDeclaration.WithBody(null)
                    .WithExpressionBody(arrowExpression)
                    .WithSemicolonToken(semicolonToken)
                    .WithAdditionalAnnotations(Formatter.Annotation));
         }
     }
     else if (methodDeclaration.ExpressionBody != null && expressionBodyPreference == ExpressionBodyPreference.Never)
     {
         if (methodDeclaration.ExpressionBody.TryConvertToBlock(
                 methodDeclaration.SemicolonToken, createReturnStatementForExpression, out var block))
         {
             return(methodDeclaration.WithExpressionBody(null)
                    .WithSemicolonToken(default)
예제 #6
0
        public static bool TryConvertToExpressionBody(
            this BlockSyntax block, SyntaxKind declarationKind,
            ParseOptions options, ExpressionBodyPreference preference,
            out ExpressionSyntax expression,
            out SyntaxToken semicolonToken)
        {
            if (preference != ExpressionBodyPreference.Never &&
                block != null && block.Statements.Count == 1)
            {
                var version           = ((CSharpParseOptions)options).LanguageVersion;
                var acceptableVersion =
                    version >= LanguageVersion.CSharp7 ||
                    (version >= LanguageVersion.CSharp6 && IsSupportedInCSharp6(declarationKind));

                if (acceptableVersion)
                {
                    var firstStatement = block.Statements[0];

                    if (TryGetExpression(version, firstStatement, out expression, out semicolonToken) &&
                        MatchesPreference(expression, preference))
                    {
                        // The close brace of the block may have important trivia on it (like
                        // comments or directives).  Preserve them on the semicolon when we
                        // convert to an expression body.
                        semicolonToken = semicolonToken.WithAppendedTrailingTrivia(
                            block.CloseBraceToken.LeadingTrivia.Where(t => !t.IsWhitespaceOrEndOfLine()));
                        return(true);
                    }
                }
            }

            expression     = null;
            semicolonToken = default;
            return(false);
        }
예제 #7
0
        public static bool TryConvertToExpressionBody(
            this BlockSyntax?block,
            LanguageVersion languageVersion,
            ExpressionBodyPreference preference,
            [NotNullWhen(true)] out ExpressionSyntax?expression,
            out SyntaxToken semicolonToken)
        {
            if (preference != ExpressionBodyPreference.Never &&
                block != null && block.Statements.Count == 1)
            {
                var firstStatement = block.Statements[0];

                if (TryGetExpression(firstStatement, languageVersion, out expression, out semicolonToken) &&
                    MatchesPreference(expression, preference))
                {
                    // The close brace of the block may have important trivia on it (like
                    // comments or directives).  Preserve them on the semicolon when we
                    // convert to an expression body.
                    semicolonToken = semicolonToken.WithAppendedTrailingTrivia(
                        block.CloseBraceToken.LeadingTrivia.Where(t => !t.IsWhitespaceOrEndOfLine()));
                    return(true);
                }
            }

            expression     = null;
            semicolonToken = default;
            return(false);
        }
        public static bool TryConvertToArrowExpressionBody(
            this BlockSyntax block,
            SyntaxKind declarationKind,
            LanguageVersion languageVersion,
            ExpressionBodyPreference preference,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?arrowExpression,
            out SyntaxToken semicolonToken)
        {
            // We can always use arrow-expression bodies in C# 7 or above.
            // We can also use them in C# 6, but only a select set of member kinds.
            var acceptableVersion =
                languageVersion >= LanguageVersion.CSharp7 ||
                (languageVersion >= LanguageVersion.CSharp6 && IsSupportedInCSharp6(declarationKind));

            if (acceptableVersion &&
                block.TryConvertToExpressionBody(languageVersion, preference, out var expression, out semicolonToken))
            {
                arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);
                return(true);
            }

            arrowExpression = null;
            semicolonToken  = default;
            return(false);
        }
예제 #9
0
        private static bool TryGetArrowExpressionBody(
            SyntaxKind declaratoinKind,
            AccessorDeclarationSyntax accessor,
            ParseOptions options,
            ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken
            )
        {
            // If the accessor has an expression body already, then use that as the expression body
            // for the property.
            if (accessor.ExpressionBody != null)
            {
                arrowExpression = accessor.ExpressionBody;
                semicolonToken  = accessor.SemicolonToken;
                return(true);
            }

            return(accessor.Body.TryConvertToArrowExpressionBody(
                       declaratoinKind,
                       options,
                       preference,
                       out arrowExpression,
                       out semicolonToken
                       ));
        }
        protected override async Task <ImmutableArray <CodeAction> > ComputeOpposingRefactoringsWhenAnalyzerActiveAsync(
            Document document, TextSpan span, ExpressionBodyPreference option, CancellationToken cancellationToken)
        {
            if (option == ExpressionBodyPreference.Never)
            {
                // the user wants block-bodies (and the analyzer will be trying to enforce that). So
                // the reverse of this is that we want to offer the refactoring to convert a
                // block-body to an expression-body whenever possible.
                return(await ComputeRefactoringsAsync(
                           document, span, ExpressionBodyPreference.WhenPossible, cancellationToken).ConfigureAwait(false));
            }
            else if (option == ExpressionBodyPreference.WhenPossible)
            {
                // the user likes expression-bodies whenever possible, and the analyzer will be
                // trying to enforce that.  So the reverse of this is that we want to offer the
                // refactoring to convert an expression-body to a block-body whenever possible.
                return(await ComputeRefactoringsAsync(
                           document, span, ExpressionBodyPreference.Never, cancellationToken).ConfigureAwait(false));
            }
            else if (option == ExpressionBodyPreference.WhenOnSingleLine)
            {
                // the user likes expression-bodies *if* the body would be on a single line. this
                // means if we hit an block-body with an expression on a single line, then the
                // analyzer will handle it for us.

                // So we need to handle the cases of either hitting an expression-body and wanting
                // to convert it to a block-body *or* hitting an block-body over *multiple* lines and
                // wanting to offer to convert to an expression-body.

                // Always offer to convert an expression to a block since the analyzer will never
                // offer that. For this option setting.
                var useBlockRefactorings = await ComputeRefactoringsAsync(
                    document, span, ExpressionBodyPreference.Never, cancellationToken).ConfigureAwait(false);

                var whenOnSingleLineRefactorings = await ComputeRefactoringsAsync(
                    document, span, ExpressionBodyPreference.WhenOnSingleLine, cancellationToken).ConfigureAwait(false);

                if (whenOnSingleLineRefactorings.Length > 0)
                {
                    // this block lambda would be converted to an expression lambda based on the
                    // analyzer alone.  So we don't want to offer that as a refactoring ourselves.
                    return(useBlockRefactorings);
                }

                // The lambda block statement wasn't on a single line.  So the analyzer would
                // not offer to convert it to an expression body.  So we should can offer that
                // as a refactoring if possible.
                var whenPossibleRefactorings = await ComputeRefactoringsAsync(
                    document, span, ExpressionBodyPreference.WhenPossible, cancellationToken).ConfigureAwait(false);

                return(useBlockRefactorings.AddRange(whenPossibleRefactorings));
            }
            else
            {
                throw ExceptionUtilities.UnexpectedValue(option);
            }
        }
예제 #11
0
 protected override bool TryConvertToExpressionBody(
     IndexerDeclarationSyntax declaration, ParseOptions options,
     ExpressionBodyPreference conversionPreference,
     out ArrowExpressionClauseSyntax arrowExpression,
     out SyntaxToken semicolonToken)
 {
     return(this.TryConvertToExpressionBodyForBaseProperty(
                declaration, options, conversionPreference,
                out arrowExpression, out semicolonToken));
 }
예제 #12
0
        internal static bool TryConvertToExpressionBody(
            LambdaExpressionSyntax declaration,
            LanguageVersion languageVersion,
            ExpressionBodyPreference conversionPreference,
            [NotNullWhen(true)] out ExpressionSyntax?expression)
        {
            var body = declaration.Body as BlockSyntax;

            return(body.TryConvertToExpressionBody(languageVersion, conversionPreference, out expression, out _));
        }
예제 #13
0
 private static bool TryConvertToExpressionBody(
     LambdaExpressionSyntax declaration,
     ParseOptions options, ExpressionBodyPreference conversionPreference,
     out ExpressionSyntax expressionWhenOnSingleLine,
     out SyntaxToken semicolonWhenOnSingleLine)
 {
     return(TryConvertToExpressionBodyWorker(
                declaration, options, conversionPreference,
                out expressionWhenOnSingleLine, out semicolonWhenOnSingleLine));
 }
예제 #14
0
        private static bool TryConvertToExpressionBodyWorker(
            LambdaExpressionSyntax declaration, ParseOptions options, ExpressionBodyPreference conversionPreference,
            out ExpressionSyntax expressionWhenOnSingleLine, out SyntaxToken semicolonWhenOnSingleLine)
        {
            var body = declaration.Body as BlockSyntax;

            return(body.TryConvertToExpressionBody(
                       declaration.Kind(), options, conversionPreference,
                       out expressionWhenOnSingleLine, out semicolonWhenOnSingleLine));
        }
예제 #15
0
 protected virtual bool TryConvertToExpressionBody(
     TDeclaration declaration,
     ExpressionBodyPreference conversionPreference,
     [NotNullWhen(true)] out ArrowExpressionClauseSyntax?expressionWhenOnSingleLine,
     out SyntaxToken semicolonWhenOnSingleLine)
 {
     return(TryConvertToExpressionBodyWorker(
                declaration, conversionPreference,
                out expressionWhenOnSingleLine, out semicolonWhenOnSingleLine));
 }
예제 #16
0
        public static bool MatchesPreference(
            ExpressionSyntax expression, ExpressionBodyPreference preference)
        {
            if (preference == ExpressionBodyPreference.WhenPossible)
            {
                return(true);
            }

            Contract.ThrowIfFalse(preference == ExpressionBodyPreference.WhenOnSingleLine);
            return(CSharpSyntaxFactsService.Instance.IsOnSingleLine(expression, fullSpan: false));
        }
예제 #17
0
        protected virtual bool TryConvertToExpressionBody(
            TDeclaration declaration,
            ParseOptions options, ExpressionBodyPreference conversionPreference,
            out ArrowExpressionClauseSyntax expressionWhenOnSingleLine,
            out SyntaxToken semicolonWhenOnSingleLine)
        {
            var body = this.GetBody(declaration);

            return(body.TryConvertToExpressionBody(options, conversionPreference,
                                                   out expressionWhenOnSingleLine, out semicolonWhenOnSingleLine));
        }
예제 #18
0
        private static object ParseExpressionBodyPreference(string value, ExpressionBodyPreference @default)
        {
            if (bool.TryParse(value, out var boolValue))
            {
                return(boolValue ? ExpressionBodyPreference.WhenPossible : ExpressionBodyPreference.Never);
            }

            if (value == "when_on_single_line")
            {
                return(ExpressionBodyPreference.WhenOnSingleLine);
            }

            return(@default);
        }
예제 #19
0
        internal static bool CanOfferUseBlockBody(
            SemanticModel semanticModel, ExpressionBodyPreference preference,
            LambdaExpressionSyntax declaration, CancellationToken cancellationToken)
        {
            var userPrefersBlockBodies = preference == ExpressionBodyPreference.Never;

            if (!userPrefersBlockBodies)
            {
                // If the user doesn't even want block bodies, then certainly do not offer.
                return(false);
            }

            var expressionBodyOpt = GetBodyAsExpression(declaration);

            if (expressionBodyOpt == null)
            {
                // they already have a block body.
                return(false);
            }

            // We need to know what sort of lambda this is (void returning or not) in order to be
            // able to create the right sort of block body (i.e. with a return-statement or
            // expr-statement).  So, if we can't figure out what lambda type this is, we should not
            // proceed.
            if (semanticModel.GetTypeInfo(declaration, cancellationToken).ConvertedType is not INamedTypeSymbol lambdaType || lambdaType.DelegateInvokeMethod == null)
            {
                return(false);
            }

            var canOffer = expressionBodyOpt.TryConvertToStatement(
                semicolonTokenOpt: null, createReturnStatementForExpression: false, out _);

            if (!canOffer)
            {
                // Couldn't even convert the expression into statement form.
                return(false);
            }

            var languageVersion = declaration.SyntaxTree.Options.LanguageVersion();

            if (expressionBodyOpt.IsKind(SyntaxKind.ThrowExpression) &&
                languageVersion < LanguageVersion.CSharp7)
            {
                // Can't convert this prior to C# 7 because ```a => throw ...``` isn't allowed.
                return(false);
            }

            return(true);
        }
예제 #20
0
        private static async Task ComputeRefactoringsAsync(
            CodeRefactoringContext context, ExpressionBodyPreference option, bool analyzerActive)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var computationTask = analyzerActive
                ? ComputeOpposingRefactoringsWhenAnalyzerActiveAsync(document, span, option, cancellationToken)
                : ComputeAllRefactoringsWhenAnalyzerInactiveAsync(document, span, cancellationToken);

            var codeActions = await computationTask.ConfigureAwait(false);

            context.RegisterRefactorings(codeActions);
        }
        private static async Task <ImmutableArray <CodeAction> > ComputeRefactoringsAsync(
            Document document,
            TextSpan span,
            ExpressionBodyPreference option,
            CancellationToken cancellationToken
            )
        {
            var lambdaNode = await document
                             .TryGetRelevantNodeAsync <LambdaExpressionSyntax>(span, cancellationToken)
                             .ConfigureAwait(false);

            if (lambdaNode == null)
            {
                return(ImmutableArray <CodeAction> .Empty);
            }

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            using var resultDisposer = ArrayBuilder <CodeAction> .GetInstance(out var result);

            if (CanOfferUseExpressionBody(option, lambdaNode))
            {
                result.Add(
                    new MyCodeAction(
                        UseExpressionBodyTitle.ToString(),
                        c => UpdateDocumentAsync(document, root, lambdaNode, c)
                        )
                    );
            }

            var semanticModel = await document
                                .GetSemanticModelAsync(cancellationToken)
                                .ConfigureAwait(false);

            if (CanOfferUseBlockBody(semanticModel, option, lambdaNode, cancellationToken))
            {
                result.Add(
                    new MyCodeAction(
                        UseBlockBodyTitle.ToString(),
                        c => UpdateDocumentAsync(document, root, lambdaNode, c)
                        )
                    );
            }

            return(result.ToImmutable());
        }
예제 #22
0
        public static bool TryConvertToArrowExpressionBody(
            this BlockSyntax block, SyntaxKind declarationKind,
            ParseOptions options, ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken)
        {
            if (!block.TryConvertToExpressionBody(
                    declarationKind, options, preference,
                    out var expression, out semicolonToken))
            {
                arrowExpression = default;
                return(false);
            }

            arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);
            return(true);
        }
예제 #23
0
        private bool TryConvertToExpressionBodyWorker(
            SyntaxNode declaration, ExpressionBodyPreference conversionPreference,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?expressionWhenOnSingleLine, out SyntaxToken semicolonWhenOnSingleLine)
        {
            var body = GetBody(declaration);

            if (body is null)
            {
                expressionWhenOnSingleLine = null;
                semicolonWhenOnSingleLine  = default;
                return(false);
            }

            var languageVersion = ((CSharpParseOptions)body.SyntaxTree.Options).LanguageVersion;

            return(body.TryConvertToArrowExpressionBody(
                       declaration.Kind(), languageVersion, conversionPreference,
                       out expressionWhenOnSingleLine, out semicolonWhenOnSingleLine));
        }
        private static ImmutableArray <SyntaxNode> ConvertPropertyToMembers(
            LanguageVersion languageVersion,
            SyntaxGenerator generator,
            IPropertySymbol property,
            PropertyDeclarationSyntax propertyDeclaration,
            IFieldSymbol?propertyBackingField,
            ExpressionBodyPreference expressionBodyPreference,
            string desiredGetMethodName,
            string desiredSetMethodName,
            CancellationToken cancellationToken)
        {
            using var _ = ArrayBuilder <SyntaxNode> .GetInstance(out var result);

            if (propertyBackingField != null)
            {
                var initializer = propertyDeclaration.Initializer?.Value;
                result.Add(generator.FieldDeclaration(propertyBackingField, initializer));
            }

            var getMethod = property.GetMethod;

            if (getMethod != null)
            {
                result.Add(GetGetMethod(
                               languageVersion,
                               generator, propertyDeclaration, propertyBackingField,
                               getMethod, desiredGetMethodName, expressionBodyPreference,
                               cancellationToken));
            }

            var setMethod = property.SetMethod;

            if (setMethod != null)
            {
                result.Add(GetSetMethod(
                               languageVersion,
                               generator, propertyDeclaration, propertyBackingField,
                               setMethod, desiredSetMethodName, expressionBodyPreference,
                               cancellationToken));
            }

            return(result.ToImmutable());
        }
예제 #25
0
        private async Task <ImmutableArray <CodeAction> > ComputeRefactoringsAsync(
            Document document, TextSpan span, ExpressionBodyPreference option, CancellationToken cancellationToken)
        {
            if (span.Length > 0)
            {
                return(ImmutableArray <CodeAction> .Empty);
            }

            var position = span.Start;

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var lambdaNode = root.FindToken(position).Parent.FirstAncestorOrSelf <LambdaExpressionSyntax>();

            if (lambdaNode == null)
            {
                return(ImmutableArray <CodeAction> .Empty);
            }

            var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var result = ArrayBuilder <CodeAction> .GetInstance();

            if (CanOfferUseExpressionBody(option, lambdaNode))
            {
                result.Add(new MyCodeAction(
                               UseExpressionBodyTitle.ToString(),
                               c => UpdateDocumentAsync(
                                   document, root, lambdaNode, c)));
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (CanOfferUseBlockBody(semanticModel, option, lambdaNode, cancellationToken))
            {
                result.Add(new MyCodeAction(
                               UseBlockBodyTitle.ToString(),
                               c => UpdateDocumentAsync(
                                   document, root, lambdaNode, c)));
            }

            return(result.ToImmutableAndFree());
        }
        private static SyntaxNode GetGetMethod(
            LanguageVersion languageVersion,
            SyntaxGenerator generator,
            PropertyDeclarationSyntax propertyDeclaration,
            IFieldSymbol?propertyBackingField,
            IMethodSymbol getMethod,
            string desiredGetMethodName,
            ExpressionBodyPreference expressionBodyPreference,
            CancellationToken cancellationToken)
        {
            var methodDeclaration = GetGetMethodWorker(
                generator, propertyDeclaration, propertyBackingField, getMethod,
                desiredGetMethodName, cancellationToken);

            methodDeclaration = CopyLeadingTrivia(propertyDeclaration, methodDeclaration, ConvertValueToReturnsRewriter.Instance);

            return(UseExpressionOrBlockBodyIfDesired(
                       languageVersion, methodDeclaration, expressionBodyPreference,
                       createReturnStatementForExpression: true));
        }
        private static SyntaxNode GetSetMethod(
            LanguageVersion languageVersion,
            SyntaxGenerator generator,
            PropertyDeclarationSyntax propertyDeclaration,
            IFieldSymbol?propertyBackingField,
            IMethodSymbol setMethod,
            string desiredSetMethodName,
            ExpressionBodyPreference expressionBodyPreference,
            CancellationToken cancellationToken)
        {
            var methodDeclaration = GetSetMethodWorker(
                generator, propertyDeclaration, propertyBackingField,
                setMethod, desiredSetMethodName, cancellationToken);

            // The analyzer doesn't report diagnostics when the trivia contains preprocessor directives, so it's safe
            // to copy the complete leading trivia to both generated methods.
            methodDeclaration = CopyLeadingTrivia(propertyDeclaration, methodDeclaration, ConvertValueToParamRewriter.Instance);

            return(UseExpressionOrBlockBodyIfDesired(
                       languageVersion, methodDeclaration, expressionBodyPreference,
                       createReturnStatementForExpression: false));
        }
예제 #28
0
        public static bool TryConvertToArrowExpressionBody(
            this BlockSyntax block,
            SyntaxKind declarationKind,
            LanguageVersion languageVersion,
            ExpressionBodyPreference preference,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?arrowExpression,
            out SyntaxToken semicolonToken)
        {
            // We can always use arrow-expression bodies in C# 7 or above.
            // We can also use them in C# 6, but only a select set of member kinds.
            var acceptableVersion =
                languageVersion >= LanguageVersion.CSharp7 ||
                (languageVersion >= LanguageVersion.CSharp6 && IsSupportedInCSharp6(declarationKind));

            if (acceptableVersion &&
                block.TryConvertToExpressionBody(languageVersion, preference, out var expression, out semicolonToken))
            {
                arrowExpression = SyntaxFactory.ArrowExpressionClause(expression);

                var parent = block.GetRequiredParent();

                if (parent.Kind() == SyntaxKind.GetAccessorDeclaration)
                {
                    var comments = parent.GetLeadingTrivia().Where(t => !t.IsWhitespaceOrEndOfLine());
                    if (!comments.IsEmpty())
                    {
                        arrowExpression = arrowExpression.WithLeadingTrivia(
                            parent.GetLeadingTrivia());
                    }
                }

                return(true);
            }

            arrowExpression = null;
            semicolonToken  = default;
            return(false);
        }
예제 #29
0
        protected override bool TryConvertToExpressionBody(
            PropertyDeclarationSyntax declaration, ParseOptions options,
            ExpressionBodyPreference conversionPreference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken)
        {
            if (base.TryConvertToExpressionBody(declaration, options, conversionPreference, out arrowExpression, out semicolonToken))
            {
                return(true);
            }

            var getAccessor = GetSingleGetAccessor(declaration.AccessorList);

            if (getAccessor?.ExpressionBody != null &&
                BlockSyntaxExtensions.MatchesPreference(getAccessor.ExpressionBody.Expression, conversionPreference))
            {
                arrowExpression = SyntaxFactory.ArrowExpressionClause(getAccessor.ExpressionBody.Expression);
                semicolonToken  = getAccessor.SemicolonToken;
                return(true);
            }

            return(false);
        }
예제 #30
0
        protected bool TryConvertToExpressionBodyForBaseProperty(
            BasePropertyDeclarationSyntax declaration,
            ExpressionBodyPreference conversionPreference,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?arrowExpression,
            out SyntaxToken semicolonToken)
        {
            if (TryConvertToExpressionBodyWorker(declaration, conversionPreference, out arrowExpression, out semicolonToken))
            {
                return(true);
            }

            var getAccessor = GetSingleGetAccessor(declaration.AccessorList);

            if (getAccessor?.ExpressionBody != null &&
                BlockSyntaxExtensions.MatchesPreference(getAccessor.ExpressionBody.Expression, conversionPreference))
            {
                arrowExpression = SyntaxFactory.ArrowExpressionClause(getAccessor.ExpressionBody.Expression);
                semicolonToken  = getAccessor.SemicolonToken;
                return(true);
            }

            return(false);
        }