예제 #1
0
        /// <summary>
        /// Gets the operation for the object being created that is being referenced by <paramref name="operation"/>.
        /// If the operation is referencing an implicit or an explicit this/base/Me/MyBase/MyClass instance, then we return "null".
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="isInsideObjectInitializer">Flag to indicate if the operation is a descendant of an <see cref="IObjectOrCollectionInitializerOperation"/> or an <see cref="IAnonymousObjectCreationOperation"/>.</param>
        /// <remarks>
        /// PERF: Note that the parameter <paramref name="isInsideObjectInitializer"/> is to improve performance by avoiding walking the entire IOperation parent for non-initializer cases.
        /// </remarks>
        public static IOperation GetInstance(this IInstanceReferenceOperation operation, bool isInsideObjectInitializer)
        {
            Debug.Assert(isInsideObjectInitializer ==
                         (operation.GetAncestor <IObjectOrCollectionInitializerOperation>(OperationKind.ObjectOrCollectionInitializer) != null ||
                          operation.GetAncestor <IAnonymousObjectCreationOperation>(OperationKind.AnonymousObjectCreation) != null));

            if (isInsideObjectInitializer)
            {
                for (IOperation current = operation; current != null && current.Kind != OperationKind.Block; current = current.Parent)
                {
                    switch (current.Kind)
                    {
                    // VB object initializer allows accessing the members of the object being created with "." operator.
                    // The syntax of such an IInstanceReferenceOperation points to the object being created.
                    // Check for such an  IObjectCreationOperation or IAnonymousObjectCreationOperation with matching syntax.
                    // For example, instance reference for members ".Field1" and ".Field2" in "New C() With { .Field1 = 0, .Field2 = .Field1 }".
                    case OperationKind.ObjectCreation:
                    case OperationKind.AnonymousObjectCreation:
                        if (current.Syntax == operation.Syntax)
                        {
                            return(current);
                        }

                        break;

                    // IInstanceReferenceOperation on left of an IMemberInitializerOperation refers to the ancestor IObjectCreationOperation/IAnonymousObjectCreationOperation/IMemberInitializerOperation.
                    // For example, implicit instance reference for member initializer "AnotherType" in "new C() { AnotherType = { IntField = 0 } };", where "AnotherType" is a member of named type kind.
                    case OperationKind.MemberInitializer:
                        var parentMemberInitializer = (IMemberInitializerOperation)current;
                        if (parentMemberInitializer.InitializedMember.DescendantsAndSelf().Contains(operation))
                        {
                            return(parentMemberInitializer.GetCreation());
                        }

                        break;

                    // IInstanceReferenceOperation on left of an ISimpleAssignmentOperation with an IObjectOrCollectionInitializerOperation parent refers to the parenting IObjectCreationOperation/IAnonymousObjectCreationOperation/IMemberInitializerOperation.
                    // For example, implicit instance reference for "IntField" in "new C() { IntField = 0 };".
                    case OperationKind.SimpleAssignment:
                        var parentSimpleAssignmentInitialier = (ISimpleAssignmentOperation)current;
                        if (parentSimpleAssignmentInitialier.Parent is IObjectOrCollectionInitializerOperation &&
                            parentSimpleAssignmentInitialier.Target.DescendantsAndSelf().Contains(operation))
                        {
                            return(parentSimpleAssignmentInitialier.Parent.Parent);
                        }

                        break;
                    }
                }
            }

            // For all other cases, IInstanceReferenceOperation refers to the implicit or explicit this/base/Me/MyBase/MyClass reference.
            // We return null for such cases.
            return(null);
        }
        /// <summary>
        /// Gets the operation for the object being created that is being referenced by <paramref name="operation"/>.
        /// If the operation is referencing an implicit or an explicit this/base/Me/MyBase/MyClass instance, then we return "null".
        /// </summary>
        public static IOperation GetInstance(this IInstanceReferenceOperation operation)
        {
            // VB object initializer allows accessing the members of the object being created with "." operator.
            // The syntax of such an IInstanceReferenceOperation points to the object being created.
            // Check for such an  IObjectCreationOperation or IAnonymousObjectCreationOperation with matching syntax.
            // For example, instance reference for members ".Field1" and ".Field2" in "New C() With { .Field1 = 0, .Field2 = .Field1 }".
            Func <IObjectCreationOperation, bool> isObjectCreation = creation => creation.Syntax == operation.Syntax;
            var objectCreation = operation.GetAncestor(OperationKind.ObjectCreation, isObjectCreation);

            if (objectCreation != null)
            {
                return(objectCreation);
            }

            Func <IAnonymousObjectCreationOperation, bool> isAnonymousObjectCreation = creation => creation.Syntax == operation.Syntax;
            var anonymousObjectCreation = operation.GetAncestor(OperationKind.AnonymousObjectCreation, isAnonymousObjectCreation);

            if (anonymousObjectCreation != null)
            {
                return(anonymousObjectCreation);
            }

            // IInstanceReferenceOperation on left of an IMemberInitializerOperation refers to the ancestor IObjectCreationOperation/IAnonymousObjectCreationOperation/IMemberInitializerOperation.
            // For example, implicit instance reference for member initializer "AnotherType" in "new C() { AnotherType = { IntField = 0 } };", where "AnotherType" is a member of named type kind.
            IMemberInitializerOperation parentMemberInitializer = operation.GetAncestor <IMemberInitializerOperation>(OperationKind.MemberInitializer);

            if (parentMemberInitializer != null &&
                parentMemberInitializer.InitializedMember.DescendantsAndSelf().Contains(operation))
            {
                return(parentMemberInitializer.GetCreation());
            }

            // IInstanceReferenceOperation on left of an ISimpleAssignmentOperation with an IObjectOrCollectionInitializerOperation parent refers to the parenting IObjectCreationOperation/IAnonymousObjectCreationOperation/IMemberInitializerOperation.
            // For example, implicit instance reference for "IntField" in "new C() { IntField = 0 };".
            ISimpleAssignmentOperation parentSimpleAssignmentInitialier = operation.GetAncestor <ISimpleAssignmentOperation>(OperationKind.SimpleAssignment);

            if (parentSimpleAssignmentInitialier != null &&
                parentSimpleAssignmentInitialier.Parent is IObjectOrCollectionInitializerOperation &&
                parentSimpleAssignmentInitialier.Target.DescendantsAndSelf().Contains(operation))
            {
                return(parentSimpleAssignmentInitialier.Parent.Parent);
            }

            // For all cases, IInstanceReferenceOperation refers to the implicit or explicit this/base/Me/MyBase/MyClass reference.
            // We return null for such cases.
            return(null);
        }