private MemoizedMethodMember(IMethodSymbol methodSymbol, IReadOnlyList <MemoizedMethodMemberArgument> parameters, SlidingCache?slidingCache, bool isAsync, string returnType, ITypeSymbol typeInCache, bool typeCanBeNull, bool typeIsReferenceType, MemoizedMethodSizeOfFunction memoizedMethodSizeOfFunction) { Name = methodSymbol.Name; IsAsync = isAsync; ReturnType = returnType; TypeInCache = typeInCache; TypeCanBeNull = typeCanBeNull; TypeIsReferenceType = typeIsReferenceType; MemoizedMethodSizeOfFunction = memoizedMethodSizeOfFunction; PartitionedParameter = parameters.FirstOrDefault(x => x.PartitionsCache);
public static bool TryCreate(GeneratorContext context, CreateMemoizeInterfaceContext interfaceContext, IMethodSymbol methodSymbol, [NotNullWhen(true)] out MemoizedMethodMember?method) { var @params = methodSymbol.Parameters; var args = new List <MemoizedMethodMemberArgument>(@params.Length); var attributes = methodSymbol.GetAttributes(); var slidingCache = SlidingCache.MaybeCreate(context, attributes); foreach (var param in @params) { if (MemoizedMethodMemberArgument.TryCreate(context, interfaceContext.ErrorLocation, param, out var arg)) { args.Add(arg); } else { method = null; return(false); } } var returnType = methodSymbol.ReturnType; var isAsync = methodSymbol.IsTaskOfTOrValueTaskOfT(); bool typeIsNullable; bool typeIsReferenceType; ITypeSymbol typeInCache; if (isAsync) { if (returnType is not INamedTypeSymbol { IsGenericType : true } namedTypeSymbol || namedTypeSymbol.TypeArguments.Length != 1) { context.CreateError("Async return types must return something", $"Expected 1 generic type argument for {methodSymbol.Name}", interfaceContext.ErrorLocation); method = null; return(false); } var taskReturnObj = namedTypeSymbol.TypeArguments[0]; // TODO check it has SizeOf() // we dont care if they are IEquatable, but we do care they implement .SizeOf() at somepoint /* * if (!taskReturnObj.AllInterfaces.Any(x => x.MetadataName == "IEquatable`1")) * { * context.CreateError("Return types must implement IEquatable", $"Async return type Task<{taskReturnObj.Name}> does not implement IEquatable", interfaceContext.ErrorLocation); * method = null; * return false; * } */ typeInCache = taskReturnObj; typeIsNullable = taskReturnObj.NullableAnnotation == NullableAnnotation.Annotated; typeIsReferenceType = taskReturnObj.IsReferenceType; } else { typeInCache = methodSymbol.ReturnType; typeIsNullable = methodSymbol.ReturnType.NullableAnnotation == NullableAnnotation.Annotated; typeIsReferenceType = methodSymbol.ReturnType.IsReferenceType; } var returnTypeAttributes = methodSymbol.GetReturnTypeAttributes(); string?globalSizeOfMethod = null; string?selfSizeOfMethod = null; // TODO [Attribute] set on the Interface that allows you to specify a class that can calculate this for you // Check TypeInCache has .SizeOfInBytes() method // Check for Attribute var sizeOfAttributeData = returnTypeAttributes.FirstOrDefault(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, context.SizeOfResultAttribute)); if (sizeOfAttributeData == null && context.GlobalSizeOfAttribute == SizeOfAttributeData.Empty) { var sizeOfInBytesMethod = typeInCache.GetMembers().OfType <IMethodSymbol>().FirstOrDefault(x => x.Name == "SizeOfInBytes" && x.ReturnType.IsLong()); if (sizeOfInBytesMethod == null) { context.CreateError("Missing SizeOfInBytes function", $"Return type '{typeInCache.ToDisplayString()}' must have a 'public long SizeOfInBytes()' function or use SizeOfResultAttribute.", interfaceContext.ErrorLocation); method = null; return(false); } else { selfSizeOfMethod = "SizeOfInBytes"; } } else { if (sizeOfAttributeData == null) { if (context.GlobalSizeOfAttribute == SizeOfAttributeData.Empty) { context.CreateError("Missing SizeOfInBytes function", $"Return type '{typeInCache.ToDisplayString()}' must have a 'public long SizeOfInBytes()' function or use SizeOfResultAttribute.", interfaceContext.ErrorLocation); method = null; return(false); } (globalSizeOfMethod, selfSizeOfMethod) = context.GlobalSizeOfAttribute; } else { (globalSizeOfMethod, selfSizeOfMethod) = SizeOfAttributeData.Parse(sizeOfAttributeData); } } var returnTypeSizeOfMethod = new MemoizedMethodSizeOfFunction(selfSizeOfMethod, globalSizeOfMethod); method = new MemoizedMethodMember(methodSymbol, args, slidingCache, isAsync, returnType.ToDisplayString(), typeInCache, typeIsNullable, typeIsReferenceType, returnTypeSizeOfMethod); return(true); }