private ITypeSymbol GetAwaitInfo(SemanticModel semanticModel, ISyntaxFactsService syntaxFactsService, SyntaxNode node, CancellationToken cancellationToken)
        {
            var awaitExpression = FirstAwaitExpressionAncestor(syntaxFactsService, node);

            var innerExpression = syntaxFactsService.GetExpressionOfAwaitExpression(awaitExpression);

            return(semanticModel.GetTypeInfo(innerExpression).Type);
        }
        private static void RemoveAwaitFromCallerIfPresent(
            SyntaxEditor editor, ISyntaxFactsService syntaxFacts,
            SyntaxNode root, ReferenceLocation referenceLocation,
            CancellationToken cancellationToken)
        {
            if (referenceLocation.IsImplicit)
            {
                return;
            }

            var location = referenceLocation.Location;
            var token    = location.FindToken(cancellationToken);

            var nameNode = token.Parent;

            if (nameNode == null)
            {
                return;
            }

            // Look for the following forms:
            //  await M(...)
            //  await <expr>.M(...)
            //  await M(...).ConfigureAwait(...)
            //  await <expr>.M(...).ConfigureAwait(...)

            var expressionNode = nameNode;

            if (syntaxFacts.IsNameOfMemberAccessExpression(nameNode))
            {
                expressionNode = nameNode.Parent;
            }

            if (!syntaxFacts.IsExpressionOfInvocationExpression(expressionNode))
            {
                return;
            }

            // We now either have M(...) or <expr>.M(...)

            var invocationExpression = expressionNode.Parent;

            Debug.Assert(syntaxFacts.IsInvocationExpression(invocationExpression));

            if (syntaxFacts.IsExpressionOfAwaitExpression(invocationExpression))
            {
                // Handle the case where we're directly awaited.
                var awaitExpression = invocationExpression.Parent;
                editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                                   syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression)
                                   .WithTriviaFrom(currentAwaitExpression));
            }
            else if (syntaxFacts.IsExpressionOfMemberAccessExpression(invocationExpression))
            {
                // Check for the .ConfigureAwait case.
                var parentMemberAccessExpression         = invocationExpression.Parent;
                var parentMemberAccessExpressionNameNode = syntaxFacts.GetNameOfMemberAccessExpression(
                    parentMemberAccessExpression);

                var parentMemberAccessExpressionName = syntaxFacts.GetIdentifierOfSimpleName(parentMemberAccessExpressionNameNode).ValueText;
                if (parentMemberAccessExpressionName == nameof(Task.ConfigureAwait))
                {
                    var parentExpression = parentMemberAccessExpression.Parent;
                    if (syntaxFacts.IsExpressionOfAwaitExpression(parentExpression))
                    {
                        var awaitExpression = parentExpression.Parent;
                        editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                        {
                            var currentConfigureAwaitInvocation = syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression);
                            var currentMemberAccess             = syntaxFacts.GetExpressionOfInvocationExpression(currentConfigureAwaitInvocation);
                            var currentInvocationExpression     = syntaxFacts.GetExpressionOfMemberAccessExpression(currentMemberAccess);
                            return(currentInvocationExpression.WithTriviaFrom(currentAwaitExpression));
                        });
                    }
                }
            }
        }
        private void RemoveAwaitFromCallerIfPresent(
            SyntaxEditor editor, ISyntaxFactsService syntaxFacts, 
            SyntaxNode root, ReferenceLocation referenceLocation,
            CancellationToken cancellationToken)
        {
            if (referenceLocation.IsImplicit)
            {
                return;
            }

            var location = referenceLocation.Location;
            var token = location.FindToken(cancellationToken);

            var nameNode = token.Parent;
            if (nameNode == null)
            {
                return;
            }

            // Look for the following forms:
            //  await M(...)
            //  await <expr>.M(...)
            //  await M(...).ConfigureAwait(...)
            //  await <expr>.M(...).ConfigureAwait(...)

            var expressionNode = nameNode;
            if (syntaxFacts.IsNameOfMemberAccessExpression(nameNode))
            {
                expressionNode = nameNode.Parent;
            }

            if (!syntaxFacts.IsExpressionOfInvocationExpression(expressionNode))
            {
                return;
            }

            // We now either have M(...) or <expr>.M(...)

            var invocationExpression = expressionNode.Parent;
            Debug.Assert(syntaxFacts.IsInvocationExpression(invocationExpression));

            if (syntaxFacts.IsExpressionOfAwaitExpression(invocationExpression))
            {
                // Handle the case where we're directly awaited.  
                var awaitExpression = invocationExpression.Parent;
                editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                    syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression)
                               .WithTriviaFrom(currentAwaitExpression));
            }
            else if (syntaxFacts.IsExpressionOfMemberAccessExpression(invocationExpression))
            {
                // Check for the .ConfigureAwait case.
                var parentMemberAccessExpression = invocationExpression.Parent;
                var parentMemberAccessExpressionNameNode = syntaxFacts.GetNameOfMemberAccessExpression(
                    parentMemberAccessExpression);

                var parentMemberAccessExpressionName = syntaxFacts.GetIdentifierOfSimpleName(parentMemberAccessExpressionNameNode).ValueText;
                if (parentMemberAccessExpressionName == nameof(Task.ConfigureAwait))
                {
                    var parentExpression = parentMemberAccessExpression.Parent;
                    if (syntaxFacts.IsExpressionOfAwaitExpression(parentExpression))
                    {
                        var awaitExpression = parentExpression.Parent;
                        editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) =>
                        {
                            var currentConfigureAwaitInvocation = syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression);
                            var currentMemberAccess = syntaxFacts.GetExpressionOfInvocationExpression(currentConfigureAwaitInvocation);
                            var currentInvocationExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(currentMemberAccess);
                            return currentInvocationExpression.WithTriviaFrom(currentAwaitExpression);
                        });
                    }
                }
            }
        }