private bool TryHandleAwait(AwaitExpressionSyntax @await)
        {
            if (@await == null)
            {
                return(false);
            }

            if (AsyncAwait.TryGetAwaitedInvocation(@await, this.semanticModel, this.cancellationToken, out InvocationExpressionSyntax invocation))
            {
                this.awaits = true;
                var symbol = this.semanticModel.GetSymbolSafe(invocation, this.cancellationToken);
                if (symbol != null)
                {
                    if (symbol.DeclaringSyntaxReferences.Length == 0)
                    {
                        this.AddReturnValue(invocation);
                    }
                    else
                    {
                        return(this.TryHandleInvocation(invocation));
                    }
                }

                return(true);
            }

            return(false);
        }
Esempio n. 2
0
        private bool TryHandleAwait(AwaitExpressionSyntax awaitExpression)
        {
            if (AsyncAwait.TryGetAwaitedInvocation(awaitExpression, this.semanticModel, this.cancellationToken, out var invocation) &&
                this.semanticModel.GetSymbolSafe(invocation, this.cancellationToken) is ISymbol symbol)
            {
                if (symbol.TrySingleDeclaration(this.cancellationToken, out MemberDeclarationSyntax declaration) &&
                    declaration is MethodDeclarationSyntax methodDeclaration)
                {
                    if (methodDeclaration.Modifiers.Any(SyntaxKind.AsyncKeyword))
                    {
                        return(this.TryHandleInvocation(invocation, out _));
                    }

                    if (this.TryGetRecursive(awaitExpression, declaration, out var walker))
                    {
                        foreach (var value in walker.returnValues)
                        {
                            AwaitValue(value);
                        }
                    }
                }
                else
                {
                    AwaitValue(invocation);
                }

                this.returnValues.RemoveAll(x => IsParameter(x));
                return(true);
            }

            return(false);

            void AwaitValue(ExpressionSyntax expression)
            {
                if (AsyncAwait.TryAwaitTaskFromResult(expression, this.semanticModel, this.cancellationToken, out var awaited))
                {
                    if (awaited is IdentifierNameSyntax identifierName &&
                        symbol is IMethodSymbol method &&
                        method.Parameters.TryFirst(x => x.Name == identifierName.Identifier.ValueText, out var parameter))
                    {
                        if (this.search != ReturnValueSearch.RecursiveInside &&
                            invocation.TryFindArgument(parameter, out var argument))
                        {
                            this.AddReturnValue(argument.Expression);
                        }
                        else if (parameter.HasExplicitDefaultValue &&
                                 parameter.TrySingleDeclaration(this.cancellationToken, out var parameterDeclaration))
                        {
                            this.returnValues.Add(parameterDeclaration.Default?.Value);
                        }
                    }

                    this.AddReturnValue(awaited);
                }
                else if (AsyncAwait.TryAwaitTaskRun(expression, this.semanticModel, this.cancellationToken, out awaited))
                {
                    if (this.TryGetRecursive(awaited, awaited, out var walker))
                    {
                        foreach (var value in walker.returnValues)
                        {
                            AwaitValue(value);
                        }
                    }
                }
                else
                {
                    this.AddReturnValue(expression);
                }
            }

            bool IsParameter(ExpressionSyntax value)
            {
                return(value is IdentifierNameSyntax id &&
                       symbol is IMethodSymbol method &&
                       method.Parameters.TryFirst(x => x.Name == id.Identifier.ValueText, out _));
            }
        }