private bool TryDecomposeIfCondition(
            IConditionalOperation ifStatement,
            out ISymbol localOrParameter)
        {
            localOrParameter = null;

            var condition = ifStatement.Condition;

            if (!(condition is IBinaryOperation binaryOperator))
            {
                return(false);
            }

            if (binaryOperator.OperatorKind != BinaryOperatorKind.Equals)
            {
                return(false);
            }

            if (IsNull(binaryOperator.LeftOperand))
            {
                return(TryGetLocalOrParameterSymbol(
                           binaryOperator.RightOperand, out localOrParameter));
            }

            if (IsNull(binaryOperator.RightOperand))
            {
                return(TryGetLocalOrParameterSymbol(
                           binaryOperator.LeftOperand, out localOrParameter));
            }

            return(false);
        }
Example #2
0
            private EvaluationResult AnalyzeConditional([NotNull] IConditionalOperation conditional)
            {
                EvaluationResult trueResult  = AnalyzeExpression(conditional.WhenTrue);
                EvaluationResult falseResult = AnalyzeExpression(conditional.WhenFalse);

                return(EvaluationResult.Unify(trueResult, falseResult));
            }
                private void Remove([NotNull] IConditionalOperation ifStatementToRemove,
                                    [NotNull] IDictionary <Location, IConditionalOperation> ifStatements)
                {
                    Location location = ifStatementToRemove.TryGetLocationForKeyword();

                    ifStatements.Remove(location);
                }
Example #4
0
        public static bool CanConvert(
            ISyntaxFacts syntaxFacts, IConditionalOperation ifOperation,
            IOperation whenTrue, IOperation whenFalse)
        {
            // Will likely screw things up if the if directive spans any preprocessor directives. So
            // do not offer for now.  Note: we pass in both the node for the ifOperation and the
            // whenFalse portion.  The whenFalse portion isn't necessary under the ifOperation.  For
            // example in:
            //
            //  ```c#
            //  #if DEBUG
            //  if (check)
            //      return 3;
            //  #endif
            //  return 2;
            //  ```
            //
            // In this case, we want to see that this cross the `#endif`
            if (syntaxFacts.SpansPreprocessorDirective(ifOperation.Syntax, whenFalse.Syntax))
            {
                return(false);
            }

            // User may have comments on the when-true/when-false statements.  These statements can
            // be very important. Often they indicate why the true/false branches are important in
            // the first place.  We don't have any place to put these, so we don't offer here.
            if (HasRegularComments(syntaxFacts, whenTrue.Syntax) ||
                HasRegularComments(syntaxFacts, whenFalse.Syntax))
            {
                return(false);
            }

            return(true);
        }
Example #5
0
        private bool TryConvertWhenAssignmentToLocalDeclaredImmediateAbove(
            ISyntaxFactsService syntaxFacts, SyntaxEditor editor, IConditionalOperation ifOperation,
            ISimpleAssignmentOperation?trueAssignment,
            ISimpleAssignmentOperation?falseAssignment,
            TExpressionSyntax conditionalExpression)
        {
            if (!TryFindMatchingLocalDeclarationImmediatelyAbove(
                    ifOperation, trueAssignment, falseAssignment,
                    out var localDeclarationOperation, out var declarator))
            {
                return(false);
            }

            // We found a valid local declaration right above the if-statement.
            var localDeclaration = localDeclarationOperation.Syntax;
            var variable         = GetDeclaratorSyntax(declarator);

            // Initialize that variable with the conditional expression.
            var updatedVariable = WithInitializer(variable, conditionalExpression);

            // Because we merged the initialization and the variable, the variable may now be able
            // to use 'var' (c#), or elide its type (vb).  Add the simplification annotation
            // appropriately so that can happen later down the line.
            var updatedLocalDeclaration = localDeclaration.ReplaceNode(variable, updatedVariable);

            updatedLocalDeclaration = AddSimplificationToType(
                (TLocalDeclarationStatementSyntax)updatedLocalDeclaration);

            editor.ReplaceNode(localDeclaration, updatedLocalDeclaration);
            editor.RemoveNode(ifOperation.Syntax, GetRemoveOptions(syntaxFacts, ifOperation.Syntax));
            return(true);
        }
Example #6
0
        /// <summary>
        /// Helper to create a conditional expression out of two original IOperation values
        /// corresponding to the whenTrue and whenFalse parts. The helper will add the appropriate
        /// annotations and casts to ensure that the conditional expression preserves semantics, but
        /// is also properly simplified and formatted.
        /// </summary>
        protected async Task <TExpressionSyntax> CreateConditionalExpressionAsync(
            Document document, IConditionalOperation ifOperation,
            IOperation trueStatement, IOperation falseStatement,
            IOperation trueValue, IOperation falseValue,
            bool isRef, CancellationToken cancellationToken)
        {
            var generator = SyntaxGenerator.GetGenerator(document);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            var condition             = ifOperation.Condition.Syntax;
            var conditionalExpression = (TConditionalExpressionSyntax)generator.ConditionalExpression(
                condition.WithoutTrivia(),
                MakeRef(generator, isRef, CastValueIfNecessary(generator, trueValue)),
                MakeRef(generator, isRef, CastValueIfNecessary(generator, falseValue)));

            conditionalExpression = conditionalExpression.WithAdditionalAnnotations(Simplifier.Annotation);
            var makeMultiLine = await MakeMultiLineAsync(
                document, condition,
                trueValue.Syntax, falseValue.Syntax, cancellationToken).ConfigureAwait(false);

            if (makeMultiLine)
            {
                conditionalExpression = conditionalExpression.WithAdditionalAnnotations(
                    SpecializedFormattingAnnotation);
            }

            return(MakeRef(generator, isRef, conditionalExpression));
        }
        private static bool ValueIsAccessed(SemanticModel semanticModel, IConditionalOperation ifOperation, IBlockOperation containingBlock, ISymbol localOrParameter, IExpressionStatementOperation expressionStatement, IAssignmentOperation assignmentExpression)
        {
            var statements               = containingBlock.Operations;
            var ifOperationIndex         = statements.IndexOf(ifOperation);
            var expressionStatementIndex = statements.IndexOf(expressionStatement);

            if (expressionStatementIndex > ifOperationIndex + 1)
            {
                // There are intermediary statements between the check and the assignment.
                // Make sure they don't try to access the local.
                var dataFlow = semanticModel.AnalyzeDataFlow(
                    statements[ifOperationIndex + 1].Syntax,
                    statements[expressionStatementIndex - 1].Syntax);

                if (dataFlow.ReadInside.Contains(localOrParameter) ||
                    dataFlow.WrittenInside.Contains(localOrParameter))
                {
                    return(true);
                }
            }

            // Also, have to make sure there is no read/write of the local/parameter on the left
            // of the assignment.  For example: map[val.Id] = val;
            var exprDataFlow = semanticModel.AnalyzeDataFlow(assignmentExpression.Target.Syntax);

            return(exprDataFlow.ReadInside.Contains(localOrParameter) ||
                   exprDataFlow.WrittenInside.Contains(localOrParameter));
        }
Example #8
0
        public static bool TryMatchPattern(
            ISyntaxFacts syntaxFacts,
            IConditionalOperation ifOperation,
            out ISimpleAssignmentOperation trueAssignment,
            out ISimpleAssignmentOperation falseAssignment)
        {
            trueAssignment  = null;
            falseAssignment = null;

            var trueStatement  = ifOperation.WhenTrue;
            var falseStatement = ifOperation.WhenFalse;

            trueStatement  = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(trueStatement);
            falseStatement = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(falseStatement);

            if (!TryGetAssignment(trueStatement, out trueAssignment) ||
                !TryGetAssignment(falseStatement, out falseAssignment))
            {
                return(false);
            }

            // The left side of both assignment statements has to be syntactically identical (modulo
            // trivia differences).
            if (!syntaxFacts.AreEquivalent(trueAssignment.Target.Syntax, falseAssignment.Target.Syntax))
            {
                return(false);
            }

            return(UseConditionalExpressionHelpers.CanConvert(
                       syntaxFacts, ifOperation, trueAssignment, falseAssignment));
        }
                public IfElseIfConstructAnalyzer([NotNull] IfStatementAnalyzer owner,
                                                 [NotNull] IConditionalOperation topIfStatement)
                {
                    this.owner = owner;

                    topIfKeywordLocation = topIfStatement.TryGetLocationForKeyword();
                    ifStatement          = topIfStatement;
                }
Example #10
0
 private static AbstractExpression ReadConditional(IConditionalOperation op)
 {
     return(new ConditionalExpression {
         Condition = ReadExpression(op.Condition),
         WhenTrue = ReadExpression(op.WhenTrue),
         WhenFalse = ReadExpression(op.WhenFalse)
     });
 }
            public override Location VisitConditional([NotNull] IConditionalOperation operation, [CanBeNull] object argument)
            {
                if (operation.IsStatement())
                {
                    var syntax = (IfStatementSyntax)operation.Syntax;
                    return(syntax.IfKeyword.GetLocation());
                }

                return(base.VisitConditional(operation, argument));
            }
Example #12
0
            public override void VisitConditional([NotNull] IConditionalOperation operation)
            {
                if (operation.IsStatement())
                {
                    Location location = operation.GetLocationForKeyword();
                    CollectedIfStatements.Add(location, operation);
                }

                base.VisitConditional(operation);
            }
            private void AnalyzeTopIfStatement()
            {
                IConditionalOperation ifStatement = ConsumeNextIfStatement();

                if (IsIfElseIfConstruct(ifStatement))
                {
                    var analyzer = new IfElseIfConstructAnalyzer(this, ifStatement);
                    analyzer.Analyze();
                }
            }
 public override void VisitConditional([NotNull] IConditionalOperation operation)
 {
     if (operation.IsStatement())
     {
         Visit(operation.Condition);
     }
     else
     {
         base.VisitConditional(operation);
     }
 }
 protected override bool TryMatchPattern(
     IConditionalOperation ifOperation,
     ISymbol containingSymbol
     ) =>
 UseConditionalExpressionForAssignmentHelpers.TryMatchPattern(
     GetSyntaxFacts(),
     ifOperation,
     out _,
     out _,
     out _,
     out _
     );
        public override TAbstractAnalysisValue VisitConditional(IConditionalOperation operation, object argument)
        {
            var _         = Visit(operation.Condition, argument);
            var whenTrue  = Visit(operation.WhenTrue, argument);
            var whenFalse = Visit(operation.WhenFalse, argument);

            if (operation.Condition.ConstantValue.HasValue &&
                operation.Condition.ConstantValue.Value is bool condition)
            {
                return(condition ? whenTrue : whenFalse);
            }

            return(ValueDomain.Merge(whenTrue, whenFalse));
        }
Example #17
0
        public override void VisitConditional(IConditionalOperation operation)
        {
            Assert.Equal(OperationKind.Conditional, operation.Kind);
            bool isRef = operation.IsRef;

            if (operation.WhenFalse != null)
            {
                AssertEx.Equal(new[] { operation.Condition, operation.WhenTrue, operation.WhenFalse }, operation.Children);
            }
            else
            {
                AssertEx.Equal(new[] { operation.Condition, operation.WhenTrue }, operation.Children);
            }
        }
        private bool TryFindAssignmentExpression(
            IBlockOperation containingBlock,
            IConditionalOperation ifOperation,
            ISymbol localOrParameter,
            out IExpressionStatementOperation expressionStatement,
            out IAssignmentOperation assignmentExpression
            )
        {
            var ifOperationIndex = containingBlock.Operations.IndexOf(ifOperation);

            // walk forward until we find an assignment of this local/parameter into
            // something else.
            for (var i = ifOperationIndex + 1; i < containingBlock.Operations.Length; i++)
            {
                expressionStatement =
                    containingBlock.Operations[i] as IExpressionStatementOperation;
                if (expressionStatement == null)
                {
                    continue;
                }

                assignmentExpression = expressionStatement.Operation as IAssignmentOperation;
                if (assignmentExpression == null)
                {
                    continue;
                }

                if (
                    !TryGetLocalOrParameterSymbol(
                        assignmentExpression.Value,
                        out var assignmentValue
                        )
                    )
                {
                    continue;
                }

                if (!Equals(localOrParameter, assignmentValue))
                {
                    continue;
                }

                return(true);
            }

            expressionStatement  = null;
            assignmentExpression = null;
            return(false);
        }
                public override void VisitConditional([NotNull] IConditionalOperation operation)
                {
                    EvaluationResult trueResult = owner.AnalyzeExpression(operation.WhenTrue);

                    if (operation.WhenFalse == null || trueResult.IsDeferred)
                    {
                        Result.CopyFrom(trueResult);
                    }
                    else
                    {
                        EvaluationResult falseResult = owner.AnalyzeExpression(operation.WhenFalse);

                        Result.CopyFrom(EvaluationResult.Unify(trueResult, falseResult));
                    }
                }
Example #20
0
        /// <summary>
        /// Helper to create a conditional expression out of two original IOperation values
        /// corresponding to the whenTrue and whenFalse parts. The helper will add the appropriate
        /// annotations and casts to ensure that the conditional expression preserves semantics, but
        /// is also properly simplified and formatted.
        /// </summary>
        protected async Task <TExpressionSyntax> CreateConditionalExpressionAsync(
            Document document, IConditionalOperation ifOperation,
            IOperation trueStatement, IOperation falseStatement,
            IOperation trueValue, IOperation falseValue,
            bool isRef, CancellationToken cancellationToken)
        {
            var generator         = SyntaxGenerator.GetGenerator(document);
            var generatorInternal = document.GetRequiredLanguageService <SyntaxGeneratorInternal>();
            var semanticModel     = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var condition = ifOperation.Condition.Syntax;

            if (!isRef)
            {
                // If we are going to generate "expr ? true : false" then just generate "expr"
                // instead.
                if (IsBooleanLiteral(trueValue, true) && IsBooleanLiteral(falseValue, false))
                {
                    return((TExpressionSyntax)condition.WithoutTrivia());
                }

                // If we are going to generate "expr ? false : true" then just generate "!expr"
                // instead.
                if (IsBooleanLiteral(trueValue, false) && IsBooleanLiteral(falseValue, true))
                {
                    return((TExpressionSyntax)generator.Negate(generatorInternal,
                                                               condition, semanticModel, cancellationToken).WithoutTrivia());
                }
            }

            var conditionalExpression = (TConditionalExpressionSyntax)generator.ConditionalExpression(
                condition.WithoutTrivia(),
                MakeRef(generatorInternal, isRef, CastValueIfNecessary(generator, trueStatement, trueValue)),
                MakeRef(generatorInternal, isRef, CastValueIfNecessary(generator, falseStatement, falseValue)));

            conditionalExpression = conditionalExpression.WithAdditionalAnnotations(Simplifier.Annotation);
            var makeMultiLine = await MakeMultiLineAsync(
                document, condition,
                trueValue.Syntax, falseValue.Syntax, cancellationToken).ConfigureAwait(false);

            if (makeMultiLine)
            {
                conditionalExpression = conditionalExpression.WithAdditionalAnnotations(
                    SpecializedFormattingAnnotation);
            }

            return(MakeRef(generatorInternal, isRef, conditionalExpression));
        }
Example #21
0
        private void ConvertOnlyIfToConditionalExpression(
            SyntaxEditor editor, IConditionalOperation ifOperation,
            ISimpleAssignmentOperation trueAssignment, ISimpleAssignmentOperation falseAssignment,
            TExpressionSyntax conditionalExpression)
        {
            var generator           = editor.Generator;
            var ifStatement         = (TIfStatementSyntax)ifOperation.Syntax;
            var expressionStatement = (TStatementSyntax)generator.ExpressionStatement(
                generator.AssignmentStatement(
                    trueAssignment.Target.Syntax,
                    conditionalExpression)).WithTriviaFrom(ifStatement);

            editor.ReplaceNode(
                ifOperation.Syntax,
                this.WrapWithBlockIfAppropriate(ifStatement, expressionStatement));
        }
        private static SyntaxNode CreateThrowIfCancellationRequestedExpressionStatement(
            DocumentEditor editor,
            IConditionalOperation conditional,
            IPropertyReferenceOperation isCancellationRequestedPropertyReference)
        {
            SyntaxNode memberAccess = editor.Generator.MemberAccessExpression(
                isCancellationRequestedPropertyReference.Instance.Syntax,
                nameof(CancellationToken.ThrowIfCancellationRequested));
            SyntaxNode invocation             = editor.Generator.InvocationExpression(memberAccess, Array.Empty <SyntaxNode>());
            var        firstWhenTrueStatement = conditional.WhenTrue is IBlockOperation block?block.Operations.FirstOrDefault() : conditional.WhenTrue;

            var result = editor.Generator.ExpressionStatement(invocation);

            result = firstWhenTrueStatement is not null?result.WithTriviaFrom(firstWhenTrueStatement.Syntax) : result;

            return(result.WithAdditionalAnnotations(Formatter.Annotation));
        }
        public static bool TryMatchPattern(
            ISyntaxFacts syntaxFacts,
            IConditionalOperation ifOperation,
            [NotNullWhen(true)] out IOperation trueStatement,
            [NotNullWhen(true)] out IOperation falseStatement,
            out ISimpleAssignmentOperation?trueAssignment,
            out ISimpleAssignmentOperation?falseAssignment)
        {
            trueAssignment  = null;
            falseAssignment = null;

            trueStatement  = ifOperation.WhenTrue;
            falseStatement = ifOperation.WhenFalse;

            trueStatement  = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(trueStatement);
            falseStatement = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(falseStatement);

            if (!TryGetAssignmentOrThrow(trueStatement, out trueAssignment, out var trueThrow) ||
                !TryGetAssignmentOrThrow(falseStatement, out falseAssignment, out var falseThrow))
            {
                return(false);
            }

            var anyAssignment = trueAssignment ?? falseAssignment;

            if (UseConditionalExpressionHelpers.HasInconvertibleThrowStatement(
                    syntaxFacts, anyAssignment?.IsRef == true, trueThrow, falseThrow))
            {
                return(false);
            }

            // The left side of both assignment statements has to be syntactically identical (modulo
            // trivia differences).
            if (trueAssignment != null && falseAssignment != null &&
                !syntaxFacts.AreEquivalent(trueAssignment.Target.Syntax, falseAssignment.Target.Syntax))
            {
                return(false);
            }

            return(UseConditionalExpressionHelpers.CanConvert(
                       syntaxFacts, ifOperation, trueStatement, falseStatement));
        }
        public static bool CanConvert(
            ISyntaxFactsService syntaxFacts, IConditionalOperation ifOperation,
            IOperation whenTrue, IOperation whenFalse)
        {
            // Will likely screw things up if the if directive spans any preprocessor directives.
            // So do not offer for now.
            if (syntaxFacts.SpansPreprocessorDirective(ifOperation.Syntax))
            {
                return(false);
            }

            // User may have comments on the when-true/when-false statements.  These statements can
            // be very important. Often they indicate why the true/false branches are important in
            // the first place.  We don't have any place to put these, so we don't offer here.
            if (HasRegularComments(syntaxFacts, whenTrue.Syntax) ||
                HasRegularComments(syntaxFacts, whenFalse.Syntax))
            {
                return(false);
            }

            return(true);
        }
 protected abstract bool TryMatchPattern(IConditionalOperation ifOperation);
 private bool HandleElseIf([NotNull] IConditionalOperation ifElseStatement)
 {
     Remove(ifElseStatement, owner.ifStatementsLeftToAnalyze);
     ifStatement = ifElseStatement;
     return(true);
 }
 private bool IsIfElseIfConstruct([NotNull] IConditionalOperation ifStatement)
 {
     return(ifStatement.WhenFalse is IConditionalOperation);
 }
Example #28
0
        private bool TryFindMatchingLocalDeclarationImmediatelyAbove(
            IConditionalOperation ifOperation,
            ISimpleAssignmentOperation?trueAssignment,
            ISimpleAssignmentOperation?falseAssignment,
            [NotNullWhen(true)] out IVariableDeclarationGroupOperation?localDeclaration,
            [NotNullWhen(true)] out IVariableDeclaratorOperation?declarator)
        {
            localDeclaration = null;
            declarator       = null;

            ILocalSymbol?local = null;

            if (trueAssignment != null)
            {
                if (!(trueAssignment.Target is ILocalReferenceOperation trueLocal))
                {
                    return(false);
                }

                local = trueLocal.Local;
            }

            if (falseAssignment != null)
            {
                if (!(falseAssignment.Target is ILocalReferenceOperation falseLocal))
                {
                    return(false);
                }

                // See if both assignments are to the same local.
                if (local != null && !Equals(local, falseLocal.Local))
                {
                    return(false);
                }

                local = falseLocal.Local;
            }

            // We weren't assigning to a local.
            if (local == null)
            {
                return(false);
            }

            // If so, see if that local was declared immediately above the if-statement.
            if (!(ifOperation.Parent is IBlockOperation parentBlock))
            {
                return(false);
            }

            var ifIndex = parentBlock.Operations.IndexOf(ifOperation);

            if (ifIndex <= 0)
            {
                return(false);
            }

            localDeclaration = parentBlock.Operations[ifIndex - 1] as IVariableDeclarationGroupOperation;
            if (localDeclaration == null)
            {
                return(false);
            }

            if (localDeclaration.IsImplicit)
            {
                return(false);
            }

            if (localDeclaration.Declarations.Length != 1)
            {
                return(false);
            }

            var declaration = localDeclaration.Declarations[0];
            var declarators = declaration.Declarators;

            if (declarators.Length != 1)
            {
                return(false);
            }

            declarator = declarators[0];
            var variable = declarator.Symbol;

            if (!Equals(variable, local))
            {
                // wasn't a declaration of the local we're assigning to.
                return(false);
            }

            var variableInitializer = declarator.Initializer ?? declaration.Initializer;

            if (variableInitializer?.Value != null)
            {
                var unwrapped = UnwrapImplicitConversion(variableInitializer.Value);
                // the variable has to either not have an initializer, or it needs to be basic
                // literal/default expression.
                if (!(unwrapped is ILiteralOperation) &&
                    !(unwrapped is IDefaultValueOperation))
                {
                    return(false);
                }
            }

            // If the variable is referenced in the condition of the 'if' block, we can't merge the
            // declaration and assignments.
            return(!ReferencesLocalVariable(ifOperation.Condition, variable));
        }
Example #29
0
 protected abstract bool TryMatchPattern(IConditionalOperation ifOperation, ISymbol containingSymbol);
Example #30
0
        public static bool TryMatchPattern(
            ISyntaxFactsService syntaxFacts,
            IConditionalOperation ifOperation,
            out IReturnOperation trueReturn,
            out IReturnOperation falseReturn)
        {
            trueReturn  = null;
            falseReturn = null;

            var trueStatement  = ifOperation.WhenTrue;
            var falseStatement = ifOperation.WhenFalse;

            // we support:
            //
            //      if (expr)
            //          return a;
            //      else
            //          return b;
            //
            // and
            //
            //      if (expr)
            //          return a;
            //
            //      return b;

            if (falseStatement == null)
            {
                var parentBlock = ifOperation.Parent as IBlockOperation;
                if (parentBlock == null)
                {
                    return(false);
                }

                var ifIndex = parentBlock.Operations.IndexOf(ifOperation);
                if (ifIndex < 0)
                {
                    return(false);
                }

                if (ifIndex + 1 < parentBlock.Operations.Length)
                {
                    falseStatement = parentBlock.Operations[ifIndex + 1];
                    if (falseStatement.IsImplicit)
                    {
                        return(false);
                    }
                }
            }

            trueStatement  = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(trueStatement);
            falseStatement = UseConditionalExpressionHelpers.UnwrapSingleStatementBlock(falseStatement);

            // Both return-statements must be of the form "return value"
            if (!(trueStatement is IReturnOperation trueReturnOp) ||
                !(falseStatement is IReturnOperation falseReturnOp) ||
                trueReturnOp.ReturnedValue == null ||
                falseReturnOp.ReturnedValue == null)
            {
                return(false);
            }

            if (trueReturnOp.Kind != falseReturnOp.Kind)
            {
                // Not allowed if these are different types of returns.  i.e.
                // "yield return ..." and "return ...".
                return(false);
            }

            if (trueReturnOp.Kind == OperationKind.YieldBreak)
            {
                // This check is just paranoia.  We likely shouldn't get here since we already
                // checked if .ReturnedValue was null above.
                return(false);
            }

            if (trueReturnOp.Kind == OperationKind.YieldReturn &&
                ifOperation.WhenFalse == null)
            {
                // we have the following:
                //
                //   if (...) {
                //       yield return ...
                //   }
                //
                //   yield return ...
                //
                // It is *not* correct to replace this with:
                //
                //      yield return ... ? ... ? ...
                //
                // as both yields need to be hit.
                return(false);
            }

            trueReturn  = trueReturnOp;
            falseReturn = falseReturnOp;

            return(UseConditionalExpressionHelpers.CanConvert(
                       syntaxFacts, ifOperation, trueReturn, falseReturn));
        }