public bool ShouldUseTap(MemberAccessExpressionSyntax memberAccessExpression) { if (memberAccessExpression.IsWrappedInAwaitExpression() || memberAccessExpression.IsWrappedInLock()) { return false; } var identifierName = memberAccessExpression.Name as IdentifierNameSyntax; if (identifierName?.Identifier.ValueText != nameof(Task<int>.Result)) { return false; } var lambdaExpression = memberAccessExpression.FirstAncestorOrSelf<LambdaExpressionSyntax>(); if (lambdaExpression == null) { var methodDeclaration = memberAccessExpression.FirstAncestorOrSelf<MethodDeclarationSyntax>(); if (methodDeclaration == null || methodDeclaration.HasOutOrRefParameters()) { return false; } } var symbol = FindSymbol(memberAccessExpression.Expression); if (symbol == null) { return false; } var taskSymbol = semanticModel.Compilation.GetTypeByMetadataName(typeof(Task).FullName); var taskOfTSymbol = semanticModel.Compilation.GetTypeByMetadataName(typeof(Task).FullName + "`1"); return symbol.IsGenericType ? symbol.ConstructedFrom.Equals(taskOfTSymbol) : symbol.Equals(taskSymbol); }
public bool ShouldUseTap(MemberAccessExpressionSyntax memberAccessExpression) { if (memberAccessExpression.IsWrappedInAwaitExpression() || memberAccessExpression.IsWrappedInLock()) { return(false); } var identifierName = memberAccessExpression.Name as IdentifierNameSyntax; if (identifierName?.Identifier.ValueText != nameof(Task <int> .Result)) { return(false); } var lambdaExpression = memberAccessExpression.FirstAncestorOrSelf <LambdaExpressionSyntax>(); if (lambdaExpression == null) { var methodDeclaration = memberAccessExpression.FirstAncestorOrSelf <MethodDeclarationSyntax>(); if (methodDeclaration == null || methodDeclaration.HasOutOrRefParameters()) { return(false); } } var symbol = FindSymbol(memberAccessExpression.Expression); if (symbol == null) { return(false); } var taskSymbol = semanticModel.Compilation.GetTypeByMetadataName(typeof(Task).FullName); var taskOfTSymbol = semanticModel.Compilation.GetTypeByMetadataName(typeof(Task).FullName + "`1"); return(symbol.IsGenericType ? symbol.ConstructedFrom.Equals(taskOfTSymbol) : symbol.Equals(taskSymbol)); }
private async Task <Document> UseAwait(Document document, MemberAccessExpressionSyntax memberAccessExpression, SyntaxNode root, CancellationToken x) { if (memberAccessExpression == null) { return(document); } var newExpression = AwaitExpression(memberAccessExpression.Expression); var originalInvocation = memberAccessExpression.FirstAncestorOrSelf <InvocationExpressionSyntax>(); var newRoot = root.ReplaceNode(originalInvocation, newExpression); return(document.WithSyntaxRoot(newRoot)); }
private static bool IsAwaited(SyntaxNodeAnalysisContext context, MemberAccessExpressionSyntax simpleMemberAccess) { var accessedSymbol = new Lazy <ISymbol>(() => context.SemanticModel.GetSymbolInfo(simpleMemberAccess.Expression).Symbol); return(simpleMemberAccess.FirstAncestorOrSelf <StatementSyntax>() is { } currentStatement && currentStatement.GetPreviousStatements().Any(statement => statement.DescendantNodes() .OfType <InvocationExpressionSyntax>() .Where(x => x.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression)) .Any(IsTaskAwaited))); bool IsTaskAwaited(InvocationExpressionSyntax invocation) => IsAwaitForMultipleTasksExecutionCall(invocation, context.SemanticModel, accessedSymbol) || IsAwaitForSingleTaskExecutionCall(invocation, context.SemanticModel, accessedSymbol); }
private static bool IsMemberAccessADynamicInvocation(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel) { var ancestorInvocation = memberAccess.FirstAncestorOrSelf <InvocationExpressionSyntax>(); if (ancestorInvocation != null && ancestorInvocation.SpanStart == memberAccess.SpanStart) { var typeInfo = semanticModel.GetTypeInfo(ancestorInvocation); if (typeInfo.Type != null && typeInfo.Type.Kind == SymbolKind.DynamicType) { return(true); } } return(false); }
/// <summary> /// Tells if the member access is dynamically invoked and cannot be reduced. In the case of /// <c>NS1.NS2.T1.T2.Method(...dynamic...)</c> we can only remove the <c>NS1.NS2</c> /// portion. The namespace part is not encoded into the IL, but the specific types in /// <c>T1.T2</c> and cannot be removed. /// </summary> private static bool IsNonRemovablePartOfDynamicMethodInvocation( SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccess, CancellationToken cancellationToken) { var ancestorInvocation = memberAccess.FirstAncestorOrSelf<InvocationExpressionSyntax>(); if (ancestorInvocation?.SpanStart == memberAccess.SpanStart) { var leftSymbol = semanticModel.GetSymbolInfo(memberAccess.Expression, cancellationToken).GetAnySymbol(); if (leftSymbol is INamedTypeSymbol) { var type = semanticModel.GetTypeInfo(memberAccess.Parent, cancellationToken).Type; if (type?.Kind == SymbolKind.DynamicType) { return true; } } } return false; }
/// <summary> /// Tells if the Member access is the starting part of a Dynamic Invocation /// </summary> /// <param name="memberAccess"></param> /// <param name="semanticModel"></param> /// <returns>Return true, if the member access is the starting point of a Dynamic Invocation</returns> private static bool IsMemberAccessADynamicInvocation(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel) { var ancestorInvocation = memberAccess.FirstAncestorOrSelf<InvocationExpressionSyntax>(); if (ancestorInvocation != null && ancestorInvocation.SpanStart == memberAccess.SpanStart) { var typeInfo = semanticModel.GetTypeInfo(ancestorInvocation); if (typeInfo.Type != null && typeInfo.Type.Kind == SymbolKind.DynamicType) { return true; } } return false; }