Example #1
0
        private static void AnalyzeOperation(OperationAnalysisContext context, Func <SyntaxNode, bool> isAttributeSytnax)
        {
            IArrayCreationOperation arrayCreationExpression = (IArrayCreationOperation)context.Operation;

            // We can't replace array allocations in attributes, as they're persisted to metadata
            // TODO: Once we have operation walkers, we can replace this syntactic check with an operation-based check.
            if (arrayCreationExpression.Syntax.Ancestors().Any(isAttributeSytnax))
            {
                return;
            }

            if (arrayCreationExpression.DimensionSizes.Length == 1)
            {
                IOperation dimensionSize = arrayCreationExpression.DimensionSizes[0];

                if (dimensionSize.HasConstantValue(0))
                {
                    // Workaround for https://github.com/dotnet/roslyn/issues/10214
                    // Bail out for compiler generated params array creation.
                    if (IsCompilerGeneratedParamsArray(arrayCreationExpression, context))
                    {
                        return;
                    }

                    // pointers can't be used as generic arguments
                    var elementType = arrayCreationExpression.GetElementType();
                    if (elementType == null)
                    {
                        return;
                    }

                    if (elementType.TypeKind != TypeKind.Pointer)
                    {
                        var arrayType = context.Compilation.GetOrCreateTypeByMetadataName(ArrayTypeName);
                        if (arrayType == null)
                        {
                            return;
                        }

                        IMethodSymbol emptyMethod = (IMethodSymbol)arrayType.GetMembers(ArrayEmptyMethodName).First();
                        var           constructed = emptyMethod.Construct(elementType);

                        string typeName = constructed.ToDisplayString(ReportFormat);
                        context.ReportDiagnostic(arrayCreationExpression.Syntax.CreateDiagnostic(UseArrayEmptyDescriptor, typeName));
                    }
                }
            }
        }
        /// <summary>
        /// Returns the constructed form of the ReducedFrom property,
        /// including the type arguments that were either inferred during reduction or supplied at the call site.
        /// </summary>
        public static IMethodSymbol GetConstructedReducedFrom(this IMethodSymbol method)
        {
            if (method.MethodKind != MethodKind.ReducedExtension)
            {
                // not a reduced extension method
                return(null);
            }

            IMethodSymbol reducedFrom = method.ReducedFrom;

            if (!reducedFrom.IsGenericMethod)
            {
                // not generic, no inferences were made
                return(reducedFrom);
            }

            ITypeSymbol[] typeArgs = new ITypeSymbol[reducedFrom.TypeParameters.Length];

            // first seed with any type arguments from reduced method
            for (int i = 0, n = method.TypeParameters.Length; i < n; i++)
            {
                ITypeSymbol arg = method.TypeArguments[i];

                // make sure we don't construct with type parameters originating from reduced symbol.
                if (arg.Equals(method.TypeParameters[i]))
                {
                    arg = method.TypeParameters[i].ReducedFrom;
                }

                typeArgs[method.TypeParameters[i].ReducedFrom.Ordinal] = arg;
            }

            // add any inferences
            for (int i = 0, n = reducedFrom.TypeParameters.Length; i < n; i++)
            {
                ITypeSymbol inferredType = method.GetTypeInferredDuringReduction(reducedFrom.TypeParameters[i]);
                if (inferredType != null)
                {
                    typeArgs[i] = inferredType;
                }
            }

            return(reducedFrom.Construct(typeArgs));
        }
Example #3
0
        public static bool CanConstructFromGenericMethodReturnType(Compilation compilation, ITypeSymbol toConstruct, ITypeSymbol toConstructFrom, IMethodSymbol method, out IMethodSymbol constructedMethod, out bool constraintsDoNotMatch)
        {
            if (!CanConstructFromReturnType(toConstruct, toConstructFrom, method, out var typeArguments))
            {
                constructedMethod     = null !;
                constraintsDoNotMatch = false;
                return(false);
            }

            if (!SatisfiesConstraints(method, typeArguments, compilation))
            {
                constructedMethod     = null !;
                constraintsDoNotMatch = true;
                return(false);
            }

            constructedMethod     = method.Construct(typeArguments);
            constraintsDoNotMatch = false;
            return(true);
        }
 public IMethodSymbol Construct(params ITypeSymbol[] typeArguments)
 {
     return(_symbol.Construct(typeArguments));
 }
 public IMethodSymbol Construct(params ITypeSymbol[] typeArguments)
 => _symbol.Construct(typeArguments);
            private IMethodSymbol Instantiate(IMethodSymbol method, IList<ITypeSymbol> invocationTypes)
            {
                // No need to instantiate if this isn't a generic method.
                if (method.TypeArguments.Length == 0)
                {
                    return method;
                }

                // Can't infer the type parameters if this method doesn't have a return type.
                // Note: this is because this code path is specifically flowing type information
                // backward through the return type.  Type information is already flowed forward
                // through arguments by the compiler when we get the initial set of methods.
                if (method.ReturnsVoid)
                {
                    return method;
                }

                // If the method has already been constructed poorly (i.e. with error types for type 
                // arguments), then unconstruct it.
                if (method.TypeArguments.All(t => t.Kind == SymbolKind.ErrorType))
                {
                    method = method.ConstructedFrom;
                }

                IDictionary<ITypeParameterSymbol, ITypeSymbol> bestMap = null;
                foreach (var type in invocationTypes)
                {
                    // Ok.  We inferred a type for this location, and we have the return type of this 
                    // method.  See if we can then assign any values for type parameters.
                    var map = DetermineTypeParameterMapping(type, method.ReturnType);
                    if (map.Count > 0 && (bestMap == null || map.Count > bestMap.Count))
                    {
                        bestMap = map;
                    }
                }

                if (bestMap == null)
                {
                    return method;
                }

                var typeArguments = method.ConstructedFrom.TypeParameters.Select(tp => bestMap.GetValueOrDefault(tp) ?? tp).ToArray();
                return method.Construct(typeArguments);
            }
Example #7
0
        private void CheckIfSpecialMethod(IMethodSymbol method)
        {
            if (IsResolvedGenericMethod(method))
            {
                if (genericMethods.Contains(method))
                {
                    return;
                }
                TrackGenericMethod(method);

                // check method overrides of this generic method and track it too
                if ((method.IsVirtual || method.IsAbstract) && !method.ContainingType.IsSealed)
                {
                    var task = SymbolFinder.FindOverridesAsync(method, solution.roslynSolution);
                    task.Wait();
                    if (!task.IsCompletedSuccessfully)
                    {
                        throw new Exception("FindOverridesAsync failed");
                    }
                    var methodOverrides = task.Result;
                    foreach (IMethodSymbol methodOverride in methodOverrides)
                    {
                        IMethodSymbol resolvedMethod = null;

                        // check if method is used in generic type
                        var genericType = genericTypes.FirstOrDefault(x => x.ConstructedFrom.IsEqual(methodOverride.ContainingType));
                        if (genericType != null)
                        {
                            resolvedMethod = (IMethodSymbol)genericType.GetMembers().First(x => x.OriginalDefinition.IsEqual(methodOverride.OriginalDefinition));
                        }

                        // construct method and track
                        if (resolvedMethod == null)
                        {
                            resolvedMethod = methodOverride.Construct(method.TypeArguments.ToArray());
                        }
                        else
                        {
                            resolvedMethod = resolvedMethod.Construct(method.TypeArguments.ToArray());
                        }

                        TrackGenericMethod(resolvedMethod);
                    }
                }

                // check overridden methods of this generic method and track it too
                if (method.IsOverride)
                {
                    var overriddenMethod = method.ConstructedFrom.OverriddenMethod;
                    while (overriddenMethod != null)
                    {
                        IMethodSymbol resolvedMethod = null;

                        // check if method is used in generic type
                        resolvedMethod = overriddenMethod.Construct(method.TypeArguments.ToArray());
                        TrackGenericMethod(resolvedMethod);

                        overriddenMethod = overriddenMethod.OverriddenMethod;
                    }
                }
            }
        }