/// <summary> /// Find all invoked methods that have an async counterpart and have not been discovered yet. /// </summary> /// <param name="methodData">The method data to be searched</param> /// <returns>Collection of invoked methods that have an async counterpart</returns> private IEnumerable <IMethodSymbol> FindNewlyInvokedMethodsWithAsyncCounterpart(MethodData methodData) { var result = new HashSet <IMethodSymbol>(); var methodDataBody = methodData.GetBodyNode(); if (methodDataBody == null) { return(result); } var documentData = methodData.TypeData.NamespaceData.DocumentData; var semanticModel = documentData.SemanticModel; var searchOptions = AsyncCounterpartsSearchOptions.Default; if (_configuration.UseCancellationTokenOverload) { searchOptions |= AsyncCounterpartsSearchOptions.HasCancellationToken; } foreach (var invocation in methodDataBody.DescendantNodes() .OfType <InvocationExpressionSyntax>()) { var methodSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol as IMethodSymbol; if (methodSymbol == null) { continue; } methodSymbol = methodSymbol.OriginalDefinition; if (result.Contains(methodSymbol)) { continue; } var asyncCounterparts = GetAsyncCounterparts(methodSymbol, searchOptions, true).ToList(); if (asyncCounterparts.Any()) { result.Add(methodSymbol); } } return(result); }
private void AnalyzeMethodData(DocumentData documentData, MethodData methodData) { foreach (var reference in methodData.InvokedMethodReferences) { AnalyzeMethodReference(documentData, reference); } var methodBody = methodData.GetBodyNode(); methodData.HasYields = methodBody?.DescendantNodes().OfType <YieldStatementSyntax>().Any() == true; methodData.MustRunSynchronized = methodData.Symbol.GetAttributes() .Where(o => o.AttributeClass.Name == "MethodImplAttribute") .Any(o => ((MethodImplOptions)(int)o.ConstructorArguments.First().Value).HasFlag(MethodImplOptions.Synchronized)); if (methodBody == null) { methodData.OmitAsync = true; } // Check if there is any if (methodData.Conversion == MethodConversion.ToAsync) { return; } // If a method is never invoked and there is no invocations inside the method body that can be async and there is no related methods we can ignore it if (!methodData.InvokedBy.Any() && methodData.InvokedMethodReferences.All(o => o.Ignore) && !methodData.RelatedMethods.Any()) { // If we have to create a new type we need to consider also the external related methods if (methodData.TypeData.Conversion != TypeConversion.NewType || !methodData.ExternalRelatedMethods.Any()) { methodData.Conversion = MethodConversion.Ignore; return; } } }