private static IMethodSymbol RemoveAttributesCore(
            this IMethodSymbol method, Func <AttributeData, bool> shouldRemoveAttribute,
            IList <SyntaxNode> statements, IList <SyntaxNode> handlesExpressions)
        {
            var methodHasAttribute = method.GetAttributes().Any(shouldRemoveAttribute);

            var someParameterHasAttribute = method.Parameters
                                            .Any(m => m.GetAttributes().Any(shouldRemoveAttribute));

            var returnTypeHasAttribute = method.GetReturnTypeAttributes().Any(shouldRemoveAttribute);

            if (!methodHasAttribute && !someParameterHasAttribute && !returnTypeHasAttribute)
            {
                return(method);
            }

            return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                       method.ContainingType,
                       method.GetAttributes().Where(a => !shouldRemoveAttribute(a)).ToList(),
                       method.DeclaredAccessibility,
                       method.GetSymbolModifiers(),
                       method.ReturnType,
                       method.ExplicitInterfaceImplementations.FirstOrDefault(),
                       method.Name,
                       method.TypeParameters,
                       method.Parameters.Select(p =>
                                                CodeGenerationSymbolFactory.CreateParameterSymbol(
                                                    p.GetAttributes().Where(a => !shouldRemoveAttribute(a)).ToList(),
                                                    p.RefKind, p.IsParams, p.Type, p.Name, p.IsOptional,
                                                    p.HasExplicitDefaultValue, p.HasExplicitDefaultValue ? p.ExplicitDefaultValue : null)).ToList(),
                       statements,
                       handlesExpressions,
                       method.GetReturnTypeAttributes().Where(a => !shouldRemoveAttribute(a)).ToList()));
        }
Example #2
0
        public static IMethodSymbol RemoveInaccessibleAttributesAndAttributesOfTypes(
            this IMethodSymbol method, ISymbol accessibleWithin,
            params INamedTypeSymbol[] removeAttributeTypes)
        {
            var methodHasAttribute = method.GetAttributes().Any(shouldRemoveAttribute);

            var someParameterHasAttribute = method.Parameters
                                            .Any(m => m.GetAttributes().Any(shouldRemoveAttribute));

            var returnTypeHasAttribute = method.GetReturnTypeAttributes().Any(shouldRemoveAttribute);

            if (!methodHasAttribute && !someParameterHasAttribute && !returnTypeHasAttribute)
            {
                return(method);
            }

            return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                       method,
                       containingType: method.ContainingType,
                       explicitInterfaceImplementations: method.ExplicitInterfaceImplementations,
                       attributes: method.GetAttributes().WhereAsArray(a => !shouldRemoveAttribute(a)),
                       parameters: method.Parameters.SelectAsArray(p =>
                                                                   CodeGenerationSymbolFactory.CreateParameterSymbol(
                                                                       p.GetAttributes().WhereAsArray(a => !shouldRemoveAttribute(a)),
                                                                       p.RefKind, p.IsParams, p.Type, p.Name, p.IsOptional,
                                                                       p.HasExplicitDefaultValue, p.HasExplicitDefaultValue ? p.ExplicitDefaultValue : null)),
                       returnTypeAttributes: method.GetReturnTypeAttributes().WhereAsArray(a => !shouldRemoveAttribute(a))));

            bool shouldRemoveAttribute(AttributeData a) =>
            removeAttributeTypes.Any(attr => attr.Equals(a.AttributeClass)) ||
            a.AttributeClass?.IsAccessibleWithin(accessibleWithin) == false;
        }
Example #3
0
        private void AddMethodSyntax(IMethodSymbol symbol, MetadataItem result, IReadOnlyList <string> typeGenericParameters, IReadOnlyList <string> methodGenericParameters)
        {
            if (!symbol.ReturnsVoid)
            {
                var id = AddSpecReference(symbol.ReturnType, typeGenericParameters, methodGenericParameters);
                result.Syntax.Return            = VisitorHelper.GetParameterDescription(symbol, result, id, true, GetTripleSlashCommentParserContext(result, _preserveRawInlineComments));
                result.Syntax.Return.Attributes = GetAttributeInfo(symbol.GetReturnTypeAttributes());
            }

            if (symbol.Parameters.Length > 0)
            {
                if (result.Syntax.Parameters == null)
                {
                    result.Syntax.Parameters = new List <ApiParameter>();
                }

                foreach (var p in symbol.Parameters)
                {
                    var id    = AddSpecReference(p.Type, typeGenericParameters, methodGenericParameters);
                    var param = VisitorHelper.GetParameterDescription(p, result, id, false, GetTripleSlashCommentParserContext(result, _preserveRawInlineComments));
                    Debug.Assert(param.Type != null);
                    param.Attributes = GetAttributeInfo(p.GetAttributes());
                    result.Syntax.Parameters.Add(param);
                }
            }
        }
            public bool HasNoCopyReturnTypeSyntax(InvocationExpressionSyntax syntax, SemanticModel model)
            {
                if (syntax == null)
                {
                    throw new ArgumentNullException(nameof(syntax));
                }
                if (model == null)
                {
                    throw new ArgumentNullException(nameof(model));
                }


                bool          ret;
                var           symbolInfo = model.GetSymbolInfo(syntax);
                IMethodSymbol methSym    = symbolInfo.Symbol as IMethodSymbol;

                if (methSym == null && symbolInfo.CandidateReason == CandidateReason.OverloadResolutionFailure &&
                    symbolInfo.CandidateSymbols.Any())
                {
                    methSym = symbolInfo.CandidateSymbols.OfType <IMethodSymbol>().FirstOrDefault();
                }


                if (methSym != null)
                {
                    INamedTypeSymbol noCopyAttributeSymbol =
                        model.Compilation.GetTypeByMetadataName(typeof(NoCopyAttribute).FullName);
                    if (noCopyAttributeSymbol != null)
                    {
                        var returnTypeAttributes = methSym.GetReturnTypeAttributes();
                        var candidateAttributes  = from attribData in returnTypeAttributes
                                                   where attribData != null
                                                   let attribDataClass = attribData.AttributeClass
                                                                         where attribDataClass.Equals(noCopyAttributeSymbol, SymbolEqualityComparer.Default) || (
                            attribDataClass is IErrorTypeSymbol ets &&
                            ets.CandidateReason == CandidateReason.NotAnAttributeType &&
                            ets.CandidateSymbols.Any(sym => sym.Name.StartsWith(UsingMandatoryAttribute.ShortenedName)))
                                                                         select attribDataClass;
                        ret = candidateAttributes.Any();
                    }
                    else
                    {
                        ret = false;
                    }
                }
                else
                {
                    ret = false;
                }

                return(ret);
            }
Example #5
0
        private static SyntaxList <AttributeListSyntax> GenerateAttributes(
            IMethodSymbol method, CodeGenerationOptions options, bool isExplicit)
        {
            var attributes = new List <AttributeListSyntax>();

            if (!isExplicit)
            {
                attributes.AddRange(AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options));
                attributes.AddRange(AttributeGenerator.GenerateAttributeLists(method.GetReturnTypeAttributes(), options, SyntaxFactory.Token(SyntaxKind.ReturnKeyword)));
            }

            return(attributes.ToSyntaxList());
        }
        public static IMethodSymbol RemoveAttributeFromParametersAndReturnType(
            this IMethodSymbol method, INamedTypeSymbol attributeType,
            IList <SyntaxNode> statements = null, IList <SyntaxNode> handlesExpressions = null)
        {
            if (attributeType == null)
            {
                return(method);
            }

            var someParameterHasAttribute = method.Parameters
                                            .Any(m => m.GetAttributes().Any(a => a.AttributeClass.Equals(attributeType)));

            var returnTypeHasAttribute = method.GetReturnTypeAttributes()
                                         .Any(a => a.AttributeClass.Equals(attributeType));

            if (!someParameterHasAttribute && !returnTypeHasAttribute)
            {
                return(method);
            }

            return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                       method.ContainingType,
                       method.GetAttributes(),
                       method.DeclaredAccessibility,
                       method.GetSymbolModifiers(),
                       method.ReturnType,
                       method.ExplicitInterfaceImplementations.FirstOrDefault(),
                       method.Name,
                       method.TypeParameters,
                       method.Parameters.Select(p =>
                                                CodeGenerationSymbolFactory.CreateParameterSymbol(
                                                    p.GetAttributes().Where(a => !a.AttributeClass.Equals(attributeType)).ToList(),
                                                    p.RefKind, p.IsParams, p.Type, p.Name, p.IsOptional,
                                                    p.HasExplicitDefaultValue, p.HasExplicitDefaultValue ? p.ExplicitDefaultValue : null)).ToList(),
                       statements,
                       handlesExpressions,
                       method.GetReturnTypeAttributes().Where(a => !a.AttributeClass.Equals(attributeType)).ToList()));
        }
        private void CheckMethod(SymbolAnalysisContext context, IMethodSymbol methodSymbol)
        {
            if (IsPrivate(methodSymbol))
            {
                return;
            }

            CheckAttributes(context, methodSymbol.GetAttributes());
            CheckAttributes(context, methodSymbol.GetReturnTypeAttributes());
            foreach (var parameter in methodSymbol.Parameters)
            {
                CheckAttributes(context, parameter.GetAttributes());
                CheckType(context, parameter.Type, parameter.DeclaringSyntaxReferences);
            }

            CheckType(context, methodSymbol.ReturnType, methodSymbol.DeclaringSyntaxReferences);
        }
 internal static IMethodSymbol CreateAccessorSymbol(
     IMethodSymbol accessor,
     IList <AttributeData> attributes      = null,
     Accessibility?accessibility           = null,
     IMethodSymbol explicitInterfaceSymbol = null,
     IList <SyntaxNode> statements         = null)
 {
     return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes,
                accessibility ?? accessor.DeclaredAccessibility,
                accessor.GetSymbolModifiers().WithIsAbstract(statements == null),
                accessor.ReturnType,
                explicitInterfaceSymbol ?? accessor.ExplicitInterfaceImplementations.FirstOrDefault(),
                accessor.Name,
                accessor.TypeParameters,
                accessor.Parameters,
                statements,
                returnTypeAttributes: accessor.GetReturnTypeAttributes()));
 }
 internal static IMethodSymbol CreateAccessorSymbol(
     IMethodSymbol accessor,
     ImmutableArray <AttributeData> attributes = default(ImmutableArray <AttributeData>),
     Accessibility?accessibility = null,
     ImmutableArray <IMethodSymbol> explicitInterfaceImplementations = default,
     ImmutableArray <SyntaxNode> statements = default(ImmutableArray <SyntaxNode>))
 {
     return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes,
                accessibility ?? accessor.DeclaredAccessibility,
                accessor.GetSymbolModifiers().WithIsAbstract(statements == null),
                accessor.ReturnType,
                accessor.ReturnsByRef,
                explicitInterfaceImplementations.IsDefault ? accessor.ExplicitInterfaceImplementations : explicitInterfaceImplementations,
                accessor.Name,
                accessor.TypeParameters,
                accessor.Parameters,
                statements,
                returnTypeAttributes: accessor.GetReturnTypeAttributes()));
 }
Example #10
0
        internal static DynamicallyAccessedMemberTypes GetDynamicallyAccessedMemberTypesOnReturnType(this IMethodSymbol methodSymbol)
        {
            AttributeData?dynamicallyAccessedMembers = null;

            foreach (var returnTypeAttribute in methodSymbol.GetReturnTypeAttributes())
            {
                if (returnTypeAttribute.AttributeClass is var attrClass && attrClass != null &&
                    attrClass.HasName(DynamicallyAccessedMembersAnalyzer.DynamicallyAccessedMembersAttribute))
                {
                    dynamicallyAccessedMembers = returnTypeAttribute;
                    break;
                }
            }

            if (dynamicallyAccessedMembers == null)
            {
                return(DynamicallyAccessedMemberTypes.None);
            }

            return((DynamicallyAccessedMemberTypes)dynamicallyAccessedMembers.ConstructorArguments[0].Value !);
        }
 internal static IMethodSymbol CreateMethodSymbol(
     IMethodSymbol method,
     IList <AttributeData> attributes      = null,
     Accessibility?accessibility           = null,
     SymbolModifiers?modifiers             = null,
     IMethodSymbol explicitInterfaceSymbol = null,
     string name = null,
     IList <SyntaxNode> statements = null)
 {
     return(CodeGenerationSymbolFactory.CreateMethodSymbol(
                attributes,
                accessibility ?? method.DeclaredAccessibility,
                modifiers ?? method.GetSymbolModifiers(),
                method.ReturnType,
                explicitInterfaceSymbol,
                name ?? method.Name,
                method.TypeParameters,
                method.Parameters,
                statements,
                returnTypeAttributes: method.GetReturnTypeAttributes()));
 }
Example #12
0
        public override void VisitMethod(IMethodSymbol symbol)
        {
            VisitAttributes(symbol);
            VisitAttributes(symbol.GetReturnTypeAttributes());

            var allLinkedSymbols = QuerySymbolsLinkedToMethod(symbol);

            foreach (var linkedSymbol in allLinkedSymbols)
            {
                linkedSymbol.Accept(this);
            }

            if (!symbol.IsAbstract)
            {
                var syntaxRef = symbol.DeclaringSyntaxReferences.FirstOrDefault();
                if (syntaxRef != null)
                {
                    VisitMethodBody(syntaxRef.GetSyntax());
                }
            }
        }
 public ImmutableArray <AttributeData> GetReturnTypeAttributes()
 {
     return(_symbol.GetReturnTypeAttributes());
 }
Example #14
0
        private async Task <Document> ConvertToLibraryImport(
            Document doc,
            MethodDeclarationSyntax methodSyntax,
            IMethodSymbol methodSymbol,
            AttributeData dllImportAttr,
            INamedTypeSymbol generatedDllImportAttrType,
            char?entryPointSuffix,
            CancellationToken cancellationToken)
        {
            DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false);

            SyntaxGenerator generator = editor.Generator;

            var dllImportSyntax = (AttributeSyntax)await dllImportAttr !.ApplicationSyntaxReference !.GetSyntaxAsync(cancellationToken).ConfigureAwait(false);

            // Create GeneratedDllImport attribute based on the DllImport attribute
            SyntaxNode generatedDllImportSyntax = GetGeneratedDllImportAttribute(
                editor,
                generator,
                dllImportSyntax,
                methodSymbol,
                generatedDllImportAttrType,
                entryPointSuffix,
                out SyntaxNode? unmanagedCallConvAttributeMaybe);

            // Add annotation about potential behavioural and compatibility changes
            generatedDllImportSyntax = generatedDllImportSyntax.WithAdditionalAnnotations(
                WarningAnnotation.Create(string.Format(Resources.ConvertToLibraryImportWarning, "[TODO] Documentation link")));

            // Replace DllImport with GeneratedDllImport
            SyntaxNode generatedDeclaration = generator.ReplaceNode(methodSyntax, dllImportSyntax, generatedDllImportSyntax);

            if (!methodSymbol.MethodImplementationFlags.HasFlag(System.Reflection.MethodImplAttributes.PreserveSig))
            {
                generatedDeclaration = await RemoveNoPreserveSigTransform(editor, generatedDeclaration, methodSymbol, cancellationToken).ConfigureAwait(false);
            }

            if (unmanagedCallConvAttributeMaybe is not null)
            {
                generatedDeclaration = generator.AddAttributes(generatedDeclaration, unmanagedCallConvAttributeMaybe);
            }

            // Replace extern keyword with partial keyword
            generatedDeclaration = generator.WithModifiers(
                generatedDeclaration,
                generator.GetModifiers(methodSyntax)
                .WithIsExtern(false)
                .WithPartial(true));

            foreach (IParameterSymbol parameter in methodSymbol.Parameters)
            {
                if (parameter.Type.SpecialType == SpecialType.System_Boolean &&
                    !parameter.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
                {
                    MethodDeclarationSyntax generatedDeclarationSyntax = (MethodDeclarationSyntax)generatedDeclaration;
                    ParameterSyntax         generatedParameterSyntax   = generatedDeclarationSyntax.ParameterList.Parameters[parameter.Ordinal];
                    generatedDeclaration = generator.ReplaceNode(generatedDeclaration, generatedParameterSyntax, generator.AddAttributes(generatedParameterSyntax,
                                                                                                                                         GenerateMarshalAsUnmanagedTypeBoolAttribute(generator)));
                }
            }

            if (methodSymbol.ReturnType.SpecialType == SpecialType.System_Boolean &&
                !methodSymbol.GetReturnTypeAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_InteropServices_MarshalAsAttribute))
            {
                generatedDeclaration = generator.AddReturnAttributes(generatedDeclaration,
                                                                     GenerateMarshalAsUnmanagedTypeBoolAttribute(generator));
            }

            // Replace the original method with the updated one
            editor.ReplaceNode(methodSyntax, generatedDeclaration);

            return(editor.GetChangedDocument());
        }
Example #15
0
        /// <summary>
        /// Get the annotated types of the formal parameters of a method and the return type.
        /// If the invocation occurs in the void context then the return type will not be significant,
        /// but if the invocation occurs within the context of an argument list to another invocation
        /// then we will need to know the annotated type which is expected to result.
        /// </summary>
        /// <param name="context">The analysis context</param>
        /// <param name="invocationExpr">A syntax node</param>
        internal virtual void AnalyzeInvocationExpr(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax invocationExpr)
        {
            //This will store the method associated with the invocation expression
            IMethodSymbol memberSymbol = null;

            if (invocationExpr.Expression is IdentifierNameSyntax identifierNameExpr)
            {
                memberSymbol = context.SemanticModel.GetSymbolInfo(identifierNameExpr).Symbol as IMethodSymbol;
            }
            else if (invocationExpr.Expression is MemberAccessExpressionSyntax memAccessExpr)
            {
                memberSymbol = context.SemanticModel.GetSymbolInfo(memAccessExpr).Symbol as IMethodSymbol;
            }
            else if (invocationExpr.Expression is MemberBindingExpressionSyntax memBindExpr)
            {
                //This was necessary to support the null propogating dot operator
                if (memBindExpr.Name is IdentifierNameSyntax identNameSyn)
                {
                    memberSymbol = context.SemanticModel.GetSymbolInfo(identNameSyn).Symbol as IMethodSymbol;
                }
            }

            //If we failed to lookup the symbol then short circuit
            if (memberSymbol == null)
            {
                return;
            }

            //Grab any attributes associated with the return type of the method
            var returnTypeAttrs = memberSymbol.GetReturnTypeAttributes();

            if (returnTypeAttrs.Count() > 0)
            {
                var retAttrStrings = ASTUtil.GetSharpCheckerAttributeStrings(returnTypeAttrs);
                if (!ASTUtil.AnnotationDictionary.ContainsKey(invocationExpr.Expression))
                {
                    ASTUtil.AnnotationDictionary.TryAdd(invocationExpr.Expression, new List <List <String> >()
                    {
                        retAttrStrings
                    });
                }
            }

            //Grab the argument list so we can interrogate it
            var argumentList = invocationExpr.ArgumentList as ArgumentListSyntax;

            for (int i = 0; i < argumentList.Arguments.Count; i++)
            {
                //Here we are handling the case where the argument is an identifier
                if (argumentList.Arguments[i].Expression is IdentifierNameSyntax argI)
                {
                    var symbol = context.SemanticModel.GetSymbolInfo(argI).Symbol;
                    if (symbol != null)
                    {
                        ASTUtil.AddSymbolAttributes(argI, symbol);
                    }
                }
                else
                {
                    //If this is another invocation expression then we should recurse
                    if (argumentList.Arguments[i].Expression is InvocationExpressionSyntax argInvExpr)
                    {
                        AnalyzeInvocationExpr(context, argInvExpr);
                    }
                    else if (argumentList.Arguments[i].Expression is ConditionalExpressionSyntax conditional)
                    {
                        //We are dealing with a ternary operator, and need to know the annotated type of each branch
                        AnalyzeExpression(context, conditional.WhenTrue);
                        AnalyzeExpression(context, conditional.WhenFalse);
                    }
                    else
                    {
                        if (context.SemanticModel.GetSymbolInfo(argumentList.Arguments[i].Expression).Symbol is IFieldSymbol fieldSymbol)
                        {
                            Debug.Assert(fieldSymbol != null, "fieldSymbol:NonNull");
                            ASTUtil.AddSymbolAttributes(argumentList.Arguments[i].Expression, fieldSymbol);
                        }
                        else if (context.SemanticModel.GetSymbolInfo(argumentList.Arguments[i].Expression).Symbol is IPropertySymbol propertySymbol)
                        {
                            Debug.Assert(propertySymbol != null, "propertySymbol:NonNull");
                            ASTUtil.AddSymbolAttributes(argumentList.Arguments[i].Expression, propertySymbol);
                        }
                    }
                }
            }

            //Check to see if any of the formal parameters of the method being invoked have associated attributes
            //In order to do this, we need to lookup the appropriate method signature.
            ImmutableArray <IParameterSymbol> paramSymbols = memberSymbol.Parameters;
            //Create the lists of lists which will hold the attributes associated with each of the attributes in the attribute list
            List <List <string> > attrListParams = new List <List <string> >();
            bool hasAttrs = false;

            //Iterate over the parameters with an explicit index so we can compare the appropriate argument below
            for (int i = 0; i < paramSymbols.Count(); i++)
            {
                //Create a new list to hold the attributes
                List <string> paramAttrs = new List <string>();

                //Get the formal parameter
                var param = paramSymbols[i];
                //Get the attributes associated with this parameter
                var attributes       = param.GetAttributes();
                var attributeStrings = ASTUtil.GetSharpCheckerAttributeStrings(attributes);

                for (int j = 0; j < attributeStrings.Count(); j++)
                {
                    var attr = attributeStrings[j];
                    paramAttrs.Add(attr);
                    hasAttrs = true;
                }

                attrListParams.Add(paramAttrs);
            }

            //If we didn't find any annotations then we return the appropriate enum value indicating as much
            if (hasAttrs)
            {
                //Add the expected attributes of the arguments to our collection
                ASTUtil.AnnotationDictionary.TryAdd(argumentList, attrListParams);
            }
        }
 public ImmutableArray <AttributeData> GetReturnTypeAttributes()
 => _symbol.GetReturnTypeAttributes();
        private static SyntaxList<AttributeListSyntax> GenerateAttributes(
            IMethodSymbol method, CodeGenerationOptions options, bool isExplicit)
        {
            var attributes = new List<AttributeListSyntax>();

            if (!isExplicit)
            {
                attributes.AddRange(AttributeGenerator.GenerateAttributeLists(method.GetAttributes(), options));
                attributes.AddRange(AttributeGenerator.GenerateAttributeLists(method.GetReturnTypeAttributes(), options, SyntaxFactory.Token(SyntaxKind.ReturnKeyword)));
            }

            return attributes.ToSyntaxList();
        }
        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);
        }
 internal static IMethodSymbol CreateAccessorSymbol(
     IMethodSymbol accessor,
     IList<AttributeData> attributes = null,
     Accessibility? accessibility = null,
     IMethodSymbol explicitInterfaceSymbol = null,
     IList<SyntaxNode> statements = null)
 {
     return CodeGenerationSymbolFactory.CreateMethodSymbol(
         attributes,
         accessibility ?? accessor.DeclaredAccessibility,
         accessor.GetSymbolModifiers().WithIsAbstract(statements == null),
         accessor.ReturnType,
         explicitInterfaceSymbol ?? accessor.ExplicitInterfaceImplementations.FirstOrDefault(),
         accessor.Name,
         accessor.TypeParameters,
         accessor.Parameters,
         statements,
         returnTypeAttributes: accessor.GetReturnTypeAttributes());
 }
 internal static IMethodSymbol CreateMethodSymbol(
     IMethodSymbol method,
     IList<AttributeData> attributes = null,
     Accessibility? accessibility = null,
     DeclarationModifiers? modifiers = null,
     IMethodSymbol explicitInterfaceSymbol = null,
     string name = null,
     IList<SyntaxNode> statements = null)
 {
     return CodeGenerationSymbolFactory.CreateMethodSymbol(
         attributes,
         accessibility ?? method.DeclaredAccessibility,
         modifiers ?? method.GetSymbolModifiers(),
         method.ReturnType,
         explicitInterfaceSymbol,
         name ?? method.Name,
         method.TypeParameters,
         method.Parameters,
         statements,
         returnTypeAttributes: method.GetReturnTypeAttributes());
 }