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)); }
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); }
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; } } } }