示例#1
0
        private static bool VerifyGetAwaiter(IMethodSymbol getAwaiter)
        {
            var returnType = getAwaiter.ReturnType;

            if (returnType == null)
            {
                return(false);
            }

            // bool IsCompleted { get }
            if (!returnType.GetMembers().OfType <IPropertySymbol>().Any(p => p.Name == WellKnownMemberNames.IsCompleted && p.Type.SpecialType == SpecialType.System_Boolean && p.GetMethod != null))
            {
                return(false);
            }

            var methods = returnType.GetMembers().OfType <IMethodSymbol>();

            // NOTE: (vladres) The current version of C# Spec, §7.7.7.3 'Runtime evaluation of await expressions', requires that
            // NOTE: the interface method INotifyCompletion.OnCompleted or ICriticalNotifyCompletion.UnsafeOnCompleted is invoked
            // NOTE: (rather than any OnCompleted method conforming to a certain pattern).
            // NOTE: Should this code be updated to match the spec?

            // void OnCompleted(Action)
            // Actions are delegates, so we'll just check for delegates.
            if (!methods.Any(x => x.Name == WellKnownMemberNames.OnCompleted && x.ReturnsVoid && x.Parameters.Length == 1 && x.Parameters.First().Type.TypeKind == TypeKind.Delegate))
            {
                return(false);
            }

            // void GetResult() || T GetResult()
            return(methods.Any(m => m.Name == WellKnownMemberNames.GetResult && !m.Parameters.Any()));
        }
示例#2
0
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
                                                     ref MethodSymbol methodSymbol, Dictionary <MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
                                                     Dictionary <string, List <MethodDeclarationSyntax> > specificationGetMethods,
                                                     List <TypeSymbol> argumentTypes = null)
 {
     return(false);
 }
示例#3
0
        private IEnumerable <IMethodSymbol> GetAsyncCounterparts(IMethodSymbol methodSymbol, ITypeSymbol invokedFromType, AsyncCounterpartsSearchOptions options, bool onlyNew = false)
        {
            if (invokedFromType == null)
            {
                return(GetAsyncCounterparts(methodSymbol, options, onlyNew));
            }
            var typeDict = _methodByTypeAsyncConterparts.GetOrAdd(invokedFromType.OriginalDefinition, new ConcurrentDictionary <IMethodSymbol, ConcurrentDictionary <AsyncCounterpartsSearchOptions, HashSet <IMethodSymbol> > >());

            return(GetAsyncCounterparts(typeDict, methodSymbol, invokedFromType.OriginalDefinition, options, onlyNew));
        }
示例#4
0
 public GetMembersVisitor(ISemanticModel semanticModel, SpecificationsElements specificationsElements,
     MethodSymbol methodSymbol, string serverFxDALInterfacesNamespace,
     ConcurrentDictionary<MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
     ConcurrentDictionary<string, MethodDeclarationSyntax> methodPerMethodSymbols,
     Dictionary<string, List<MethodDeclarationSyntax>> getMethods, List<MethodDeclarationSyntax> extensionMethods)
     : this(semanticModel, specificationsElements, serverFxDALInterfacesNamespace, semanticModelPerMethods,
         methodPerMethodSymbols, getMethods, extensionMethods,
         new Dictionary<string, PropertyDependence>(), new Dictionary<string, int>(), 0,
         new List<MethodSymbol>() { methodSymbol }, true)
 {
     _fromOriginalMethod = true;
 }
示例#5
0
 public GetMembersVisitor(ISemanticModel semanticModel, SpecificationsElements specificationsElements,
                          MethodSymbol methodSymbol, string serverFxDALInterfacesNamespace,
                          ConcurrentDictionary <MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
                          ConcurrentDictionary <string, MethodDeclarationSyntax> methodPerMethodSymbols,
                          Dictionary <string, List <MethodDeclarationSyntax> > getMethods, List <MethodDeclarationSyntax> extensionMethods)
     : this(
         semanticModel, specificationsElements, serverFxDALInterfacesNamespace, semanticModelPerMethods,
         methodPerMethodSymbols, getMethods, extensionMethods,
         new Dictionary <string, PropertyDependence>(), new Dictionary <string, int>(), 0,
         new List <MethodSymbol>() { methodSymbol }, true)
 {
     _fromOriginalMethod = true;
 }
        private IEnumerable <IMethodSymbol> GetAsyncCounterparts(ConcurrentDictionary <IMethodSymbol, ConcurrentDictionary <AsyncCounterpartsSearchOptions, HashSet <IMethodSymbol> > > asyncCounterparts,
                                                                 IMethodSymbol methodSymbol, ITypeSymbol invokedFromType, AsyncCounterpartsSearchOptions options, bool onlyNew = false)
        {
            var dict = asyncCounterparts.GetOrAdd(methodSymbol, new ConcurrentDictionary <AsyncCounterpartsSearchOptions, HashSet <IMethodSymbol> >());

            if (dict.TryGetValue(options, out var asyncMethodSymbols))
            {
                return(onlyNew ? Enumerable.Empty <IMethodSymbol>() : asyncMethodSymbols);
            }
            asyncMethodSymbols = new HashSet <IMethodSymbol>(_configuration.FindAsyncCounterpartsFinders
                                                             .SelectMany(o => o.FindAsyncCounterparts(methodSymbol, invokedFromType, options)));
            return(dict.AddOrUpdate(
                       options,
                       asyncMethodSymbols,
                       (k, v) =>
            {
                _logger.Debug($"Performance hit: Multiple GetAsyncCounterparts method calls for method symbol {methodSymbol}");
                return asyncMethodSymbols;
            }));
        }
示例#7
0
        /// <summary>
        /// If the <paramref name="symbol"/> is a method symbol, returns True if the method's return type is "awaitable".
        /// If the <paramref name="symbol"/> is a type symbol, returns True if that type is "awaitable".
        /// An "awaitable" is any type that exposes a GetAwaiter method which returns a valid "awaiter". This GetAwaiter method may be an instance method or an extension method.
        /// </summary>
        public static bool IsAwaitable(this ISymbol symbol, SemanticModel semanticModel, int position)
        {
            IMethodSymbol methodSymbol = symbol as IMethodSymbol;
            ITypeSymbol   typeSymbol   = null;

            if (methodSymbol == null)
            {
                typeSymbol = symbol as ITypeSymbol;
                if (typeSymbol == null)
                {
                    return(false);
                }
            }
            else
            {
                if (methodSymbol.ReturnType == null)
                {
                    return(false);
                }

                // dynamic
                if (methodSymbol.ReturnType.TypeKind == TypeKind.Dynamic &&
                    methodSymbol.MethodKind != MethodKind.BuiltinOperator)
                {
                    return(true);
                }
            }

            // otherwise: needs valid GetAwaiter
            var potentialGetAwaiters = semanticModel.LookupSymbols(position,
                                                                   container: typeSymbol ?? methodSymbol.ReturnType.OriginalDefinition,
                                                                   name: WellKnownMemberNames.GetAwaiter,
                                                                   includeReducedExtensionMethods: true);
            var getAwaiters = potentialGetAwaiters.OfType <IMethodSymbol>().Where(x => !x.Parameters.Any());

            return(getAwaiters.Any(VerifyGetAwaiter));
        }
示例#8
0
 IParameterHintingData IParameterHintingDataFactory.CreateTypeParameterDataProvider(Microsoft.CodeAnalysis.IMethodSymbol method)
 {
     return(new TypeParameterHintingData(method));
 }
示例#9
0
文件: Mocks.cs 项目: bnjMichel/waqs
 public bool GetSpecificationEquivalentMethod(ref MethodSymbol methodSymbol, List<TypeSymbol> argumentTypes = null)
 {
     return false;
 }
示例#10
0
 IParameterHintingData IParameterHintingDataFactory.CreateConstructorProvider(Microsoft.CodeAnalysis.IMethodSymbol constructor)
 {
     return(new ParameterHintingData(constructor));
 }
示例#11
0
文件: Mocks.cs 项目: bnjMichel/waqs
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
     ref MethodSymbol methodSymbol, Dictionary<MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
     Func<IEnumerable<MethodDeclarationSyntax>> getMethods)
 {
     return false;
 }
示例#12
0
文件: Mocks.cs 项目: bnjMichel/waqs
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
     ref MethodSymbol methodSymbol, Dictionary<MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
     IEnumerable<MethodDeclarationSyntax> candidatesMethods, string defaultClassName = null)
 {
     return false;
 }
        private static bool VerifyGetAwaiter(IMethodSymbol getAwaiter)
        {
            var returnType = getAwaiter.ReturnType;
            if (returnType == null)
            {
                return false;
            }

            // bool IsCompleted { get }
            if (!returnType.GetMembers().OfType<IPropertySymbol>().Any(p => p.Name == WellKnownMemberNames.IsCompleted && p.Type.SpecialType == SpecialType.System_Boolean && p.GetMethod != null))
            {
                return false;
            }

            var methods = returnType.GetMembers().OfType<IMethodSymbol>();

            // NOTE: (vladres) The current version of C# Spec, §7.7.7.3 'Runtime evaluation of await expressions', requires that
            // NOTE: the interface method INotifyCompletion.OnCompleted or ICriticalNotifyCompletion.UnsafeOnCompleted is invoked
            // NOTE: (rather than any OnCompleted method conforming to a certain pattern).
            // NOTE: Should this code be updated to match the spec?

            // void OnCompleted(Action) 
            // Actions are delegates, so we'll just check for delegates.
            if (!methods.Any(x => x.Name == WellKnownMemberNames.OnCompleted && x.ReturnsVoid && x.Parameters.Length == 1 && x.Parameters.First().Type.TypeKind == TypeKind.Delegate))
            {
                return false;
            }

            // void GetResult() || T GetResult()
            return methods.Any(m => m.Name == WellKnownMemberNames.GetResult && !m.Parameters.Any());
        }
示例#14
0
文件: Mocks.cs 项目: bnjMichel/waqs
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
     ref MethodSymbol methodSymbol, Dictionary<MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
     Dictionary<string, List<MethodDeclarationSyntax>> specificationGetMethods,
     List<TypeSymbol> argumentTypes = null)
 {
     return false;
 }
示例#15
0
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
                                                     ref MethodSymbol methodSymbol, Dictionary <MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
                                                     IEnumerable <MethodDeclarationSyntax> candidatesMethods, string defaultClassName = null)
 {
     return(false);
 }
示例#16
0
 public static bool GetSpecificationEquivalentMethod(SpecificationsElements specificationsElements,
                                                     ref MethodSymbol methodSymbol, Dictionary <MethodDeclarationSyntax, ISemanticModel> semanticModelPerMethods,
                                                     Func <IEnumerable <MethodDeclarationSyntax> > getMethods)
 {
     return(false);
 }
示例#17
0
 private IEnumerable <IMethodSymbol> GetAsyncCounterparts(IMethodSymbol methodSymbol, AsyncCounterpartsSearchOptions options, bool onlyNew = false)
 {
     return(GetAsyncCounterparts(_methodAsyncConterparts, methodSymbol, null, options, onlyNew));
 }
示例#18
0
 public bool GetSpecificationEquivalentMethod(ref MethodSymbol methodSymbol, List <TypeSymbol> argumentTypes = null)
 {
     return(false);
 }
示例#19
0
        /// <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>
        /// <param name="searchReferences">A set where the methods that had an invalid SearchForMethodReferences setting will be added</param>
        /// <returns>Collection of invoked methods that have an async counterpart</returns>
        private IEnumerable <IMethodSymbol> FindNewlyInvokedMethodsWithAsyncCounterpart(FunctionData methodData, ISet <IMethodSymbol> searchReferences)
        {
            if (!_scannedMethodBodies.TryAdd(methodData))
            {
                return(Enumerable.Empty <IMethodSymbol>());
            }

            var result         = new HashSet <IMethodSymbol>();
            var methodDataBody = methodData.GetBodyNode();

            if (methodDataBody == null)
            {
                return(result);
            }
            var documentData  = methodData.TypeData.NamespaceData.DocumentData;
            var semanticModel = documentData.SemanticModel;

            foreach (var node in methodDataBody.DescendantNodes().Where(o => o.IsKind(SyntaxKind.InvocationExpression) || o.IsKind(SyntaxKind.IdentifierName)))
            {
                IMethodSymbol methodSymbol = null;
                ITypeSymbol   typeSymbol   = null;
                var           invocation   = node as InvocationExpressionSyntax;
                if (invocation != null)
                {
                    if (invocation.Expression is SimpleNameSyntax)
                    {
                        typeSymbol = methodData.Symbol.ContainingType;
                    }
                    else if (invocation.Expression is MemberAccessExpressionSyntax memberAccessExpression)
                    {
                        typeSymbol = semanticModel.GetTypeInfo(memberAccessExpression.Expression).Type;
                    }

                    if (invocation.Expression.ToString() == "nameof")
                    {
                        methodSymbol = semanticModel.GetSymbolInfo(
                            invocation.ArgumentList.Arguments.First().Expression)
                                       .CandidateSymbols
                                       .OfType <IMethodSymbol>()
                                       .FirstOrDefault();
                    }
                    else
                    {
                        var symbolInfo = semanticModel.GetSymbolInfo(invocation.Expression);
                        // Will happen for dynamic
                        if (symbolInfo.Symbol == null)
                        {
                            var candidates = symbolInfo.CandidateSymbols.OfType <IMethodSymbol>().ToList();
                            methodSymbol = candidates.FirstOrDefault();
                            foreach (var candidateSymbol in candidates.Skip(1))
                            {
                                ProcessMethod(candidateSymbol, typeSymbol, invocation);
                            }
                        }
                        else
                        {
                            methodSymbol = semanticModel.GetSymbolInfo(invocation.Expression).Symbol as IMethodSymbol;
                        }
                    }
                }
                else if (node is IdentifierNameSyntax identifier)
                {
                    if (identifier.Identifier.ToString() == "var")
                    {
                        continue;
                    }
                    var propertySymbol = semanticModel.GetSymbolInfo(identifier).Symbol as IPropertySymbol;
                    if (propertySymbol == null)
                    {
                        continue;
                    }
                    typeSymbol = propertySymbol.ContainingType;
                    var isAssigned = identifier.IsAssigned();
                    methodSymbol = isAssigned ? propertySymbol.SetMethod : propertySymbol.GetMethod;
                    // Auto-properties are skipped as they can never throw a non fatal exception
                    if (!methodData.WrapInTryCatch &&
                        (methodSymbol?.IsVirtualAbstractOrInterface() == true || methodSymbol?.IsAutoPropertyAccessor() != true) &&
                        node.Ancestors().First(o => o.IsFunction()) == methodData.GetNode())
                    {
                        if (isAssigned)
                        {
                            methodData.WrapInTryCatch = true;
                        }
                        // Here we don't know if there is any precondition
                        else if (_configuration.ExceptionHandling.CatchPropertyGetterCalls(methodSymbol))
                        {
                            methodData.CatchPropertyGetterCalls.Add(identifier);
                        }
                    }
                }

                if (!ProcessMethod(methodSymbol, typeSymbol, invocation))
                {
                    continue;
                }

                // Check if there is any method passed as argument that have also an async counterpart
                // ReSharper disable once PossibleNullReferenceException
                foreach (var argument in invocation.ArgumentList.Arguments
                         .Where(o => o.Expression.IsKind(SyntaxKind.SimpleMemberAccessExpression) || o.Expression.IsKind(SyntaxKind.IdentifierName)))
                {
                    if (!(semanticModel.GetSymbolInfo(argument.Expression).Symbol is IMethodSymbol argMethodSymbol))
                    {
                        continue;
                    }
                    if (GetAsyncCounterparts(argMethodSymbol.OriginalDefinition, _searchOptions, true).Any())
                    {
                        result.Add(argMethodSymbol);
                    }
                }
            }
            return(result);


            bool ProcessMethod(IMethodSymbol methodSymbol, ITypeSymbol typeSymbol, InvocationExpressionSyntax invocation)
            {
                if (methodSymbol == null)
                {
                    return(false);
                }

                methodSymbol = methodSymbol.OriginalDefinition;
                if (result.Contains(methodSymbol))
                {
                    return(false);
                }
                // If an internal method was ignored from searching its references but we found out that it is used inside the project,
                // we must override the user setting and search for its references in order to prevent generating an invalid code
                if (!_configuration.CanSearchForMethodReferences(methodSymbol) && ProjectData.Contains(methodSymbol) &&
                    _mustScanForMethodReferences.TryAdd(methodSymbol))
                {
                    searchReferences.Add(methodSymbol);
                    ProjectData.GetFunctionData(methodSymbol).AddDiagnostic(
                        $"Overriding SearchForMethodReferences user setting, as we found a reference inside method {methodData.Symbol}",
                        DiagnosticSeverity.Info);
                }

                // Add method only if new
                if (GetAsyncCounterparts(methodSymbol, typeSymbol, _searchOptions, true).Any())
                {
                    result.Add(methodSymbol);
                }
                if (invocation == null || !GetAsyncCounterparts(methodSymbol, typeSymbol, _searchOptions).Any())
                {
                    return(false);
                }

                return(true);
            }
        }