public static bool DoesMethodUseTAsObject(IMethodSymbol method, SemanticModel semanticModel,
                                                  ITypeParameterSymbol typeParameter, IMethodSymbol[] relevantObjectMethods, KnownSymbols knownSymbols,
                                                  RecursiveStateForNotUsedAsObject recursiveStateForNotUsedAsObject)
        {
            if (recursiveStateForNotUsedAsObject.ItemsInStack.Contains((method, typeParameter)))
            {
                return(false);
            }

            recursiveStateForNotUsedAsObject = recursiveStateForNotUsedAsObject.Add(method, typeParameter);

            if (typeParameter.GetAttributes().Any(x => Utils.IsNotUsedAsObjectAttribute(x.AttributeClass.Name)))
            {
                return(false);
            }

            if (method.GetAttributes().Any(x =>
                                           Utils.IsDoesNotUseClassTypeParameterAsObjectAttributeForTypeParameter(x, typeParameter.Name)))
            {
                return(false);
            }

            if (method.IsInCode())
            {
                var location = method.Locations.First();

                var locationSourceTree = location.SourceTree;

                var methodSyntax = locationSourceTree.GetRoot().FindNode(location.SourceSpan);

                return(GetNodesWhereTIsUsedAsObject(methodSyntax, semanticModel, relevantObjectMethods, typeParameter,
                                                    knownSymbols, recursiveStateForNotUsedAsObject).Any());
            }

            if (typeParameter.DeclaringMethod != null)
            {
                if (knownSymbols.KnownNotUsedAsObjectMethodTypeParameters.TryGetValue(
                        Utils.GetFullMetaDataName(typeParameter.DeclaringMethod.ContainingType),
                        out var methods) &&
                    methods.Keys.FirstOrNoValue(x => x.Matches(typeParameter.DeclaringMethod))
                    .HasValueAnd(x => methods[x].Contains(typeParameter.Name)))
                {
                    return(false);
                }
            }
            else
            {
                if (knownSymbols.KnownNotUsedAsObjectClassTypeParameters.TryGetValue(
                        Utils.GetFullMetaDataName(typeParameter.DeclaringType),
                        out var methods) &&
                    methods.Contains(typeParameter.Name))
                {
                    return(false);
                }
            }

            return(true);
        }
        public static bool DoesMethodUseTAsObject_IncludingStaticConstructorsIfRelevant(
            IMethodSymbol method,
            SemanticModel semanticModel,
            ITypeParameterSymbol typeParameter,
            IMethodSymbol[] relevantObjectMethods,
            KnownSymbols knownSymbols,
            RecursiveStateForNotUsedAsObject recursiveStateForNotUsedAsObject)
        {
            IEnumerable <INamedTypeSymbol> GetAllContainingTypes()
            {
                var containingType = method.ContainingType;

                while (containingType != null)
                {
                    yield return(containingType);

                    containingType = containingType.ContainingType;
                }
            }

            if (method.IsStatic || method.MethodKind == MethodKind.Constructor)
            {
                var containingTypes = GetAllContainingTypes().ToList();

                var staticConstructors = containingTypes.SelectMany(x => x.StaticConstructors).ToList();

                if (staticConstructors
                    .Any(c =>
                         DoesMethodUseTAsObject(c, semanticModel, typeParameter, relevantObjectMethods, knownSymbols, recursiveStateForNotUsedAsObject)))
                {
                    return(true);
                }
            }

            return(DoesMethodUseTAsObject(method, semanticModel, typeParameter, relevantObjectMethods, knownSymbols, recursiveStateForNotUsedAsObject));
        }
        public static IEnumerable <SyntaxNode> GetNodesWhereTIsUsedAsObject(SyntaxNode scope,
                                                                            SemanticModel semanticModel,
                                                                            IMethodSymbol[] relevantObjectMethods,
                                                                            ITypeParameterSymbol typeParameterSymbol,
                                                                            KnownSymbols knownSymbols,
                                                                            RecursiveStateForNotUsedAsObject recursiveStateForNotUsedAsObject)
        {
            var objectType = semanticModel.Compilation.ObjectType;

            var invocationOperations = scope.DescendantNodes()
                                       .OfType <InvocationExpressionSyntax>()
                                       .Select(x => semanticModel.GetOperation(x))
                                       .OfType <IInvocationOperation>()
                                       .Where(x => x.TargetMethod.ContainingType.TypeKind != TypeKind.Delegate)
                                       .ToList();

            var invocationsOfObjectMethodsOnExpressionsOfTypeT =
                invocationOperations
                .Where(x => x.Instance?.Type.Equals(typeParameterSymbol) ?? false)
                .Where(x => relevantObjectMethods.Contains(x.TargetMethod))
                .ToList();

            foreach (var inv in invocationsOfObjectMethodsOnExpressionsOfTypeT)
            {
                yield return(inv.Syntax);
            }

            var conversions =
                Utils.GetConversions(scope, semanticModel);


            var conversionsFromTToObject =
                conversions.Where(x => [email protected](typeParameterSymbol) &&
                                  x.to.Equals(objectType))
                .Select(x => x.node)
                .ToList();

            foreach (var conv in conversionsFromTToObject)
            {
                yield return(conv);
            }



            var constructionOperations =
                scope.DescendantNodes()
                .OfType <ObjectCreationExpressionSyntax>()
                .Select(x => semanticModel.GetOperation(x))
                .OfType <IObjectCreationOperation>()
                .Where(x => x.Constructor.ContainingType.TypeKind != TypeKind.Delegate)
                .ToList();



            var invokedMethodsAndConstructorsWithRelevantTypeParameters =
                invocationOperations
                .Select(x => (Method: x.TargetMethod, x.Syntax))
                .Concat(constructionOperations.Select(x => (Method: x.Constructor, x.Syntax)))
                .Select(x => (
                            node: x.Syntax,
                            method: x.Method,
                            typeParamsAndArgs:
                            GetTypeParametersAndMatchingArguments(x.Method)
                            .Where(p =>
                                   p.argument.Equals(typeParameterSymbol)).ToList()))
                .ToList();

            foreach (var invokedMethodOrConstructor in invokedMethodsAndConstructorsWithRelevantTypeParameters)
            {
                foreach (var tp in invokedMethodOrConstructor.typeParamsAndArgs)
                {
                    if (DoesMethodUseTAsObject_IncludingStaticConstructorsIfRelevant(
                            invokedMethodOrConstructor.method,
                            semanticModel,
                            tp.typeParameter,
                            relevantObjectMethods,
                            knownSymbols,
                            recursiveStateForNotUsedAsObject))
                    {
                        yield return(invokedMethodOrConstructor.node);

                        break;
                    }
                }
            }
        }