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); }
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 _)); } }
private void AddReturnValue(ExpressionSyntax value) { if (this.awaits) { if (AsyncAwait.TryAwaitTaskRun(value, this.semanticModel, this.cancellationToken, out ExpressionSyntax awaited)) { using (var pooled = this.GetRecursive(awaited)) { if (pooled.Item.values.Count == 0) { this.values.Add(awaited); } else { foreach (var returnValue in pooled.Item.values) { this.AddReturnValue(returnValue); } } } return; } if (AsyncAwait.TryAwaitTaskFromResult(value, this.semanticModel, this.cancellationToken, out awaited)) { this.AddReturnValue(awaited); return; } if (this.search == Search.Recursive && value is AwaitExpressionSyntax @await) { value = @await.Expression; } } if (this.search == Search.Recursive) { if (value is InvocationExpressionSyntax invocation) { var method = this.semanticModel.GetSymbolSafe(invocation, this.cancellationToken); if (method == null || method.DeclaringSyntaxReferences.Length == 0) { this.values.Add(value); } else { using (var pooled = this.GetRecursive(value)) { foreach (var returnValue in pooled.Item.values) { this.AddReturnValue(returnValue); } } } } else if (this.recursionLoop.Add(value) && this.semanticModel.IsEither <IParameterSymbol, ILocalSymbol>(value, this.cancellationToken)) { using (var pooled = AssignedValueWalker.Create(value, this.semanticModel, this.cancellationToken)) { if (pooled.Item.Count == 0) { this.values.Add(value); } else { foreach (var assignment in pooled.Item) { this.AddReturnValue(assignment); } } } } else { this.values.Add(value); } } else { this.values.Add(value); } }