예제 #1
0
        public override DifferenceType Diff(IDifferences differences, Mappings.MemberMapping mapping)
        {
            ITypeDefinitionMember impl     = mapping[0];
            ITypeDefinitionMember contract = mapping[1];

            if (impl == null)
            {
                return(DifferenceType.Unknown);
            }

            if (contract == null && impl.IsAbstract())
            {
                // If the type is effectively sealed then it is ok to remove abstract members
                ITypeDefinition contractType = mapping.ContainingType[1];
                // We check that interfaces have the same number of members in another rule so there is no need to check that here.
                if (contractType != null && (contractType.IsEffectivelySealed() || (contractType.IsInterface && mapping.ContainingType[0].IsInterface)))
                {
                    return(DifferenceType.Unknown);
                }

                differences.AddIncompatibleDifference(this, impl.GetMemberViolationMessage("Member", $"is abstract in the {Implementation}", $"is missing in the {Contract}"));
                return(DifferenceType.Changed);
            }
            return(DifferenceType.Unknown);
        }
예제 #2
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            bool isImplOverridable     = IsOverridable(impl);
            bool isContractOverridable = IsOverridable(contract);

            /*
             * //@todo: Move to a separate rule that's only run in "strict" mode.
             * if (isImplInhertiable && !isContractInheritiable)
             * {
             *  // This is separate because it can be noisy and is generally allowed as long as it is reviewed properly.
             *  differences.AddIncompatibleDifference("CannotMakeMemberVirtual",
             *      "Member '{0}' is virtual in the implementation but non-virtual in the contract.",
             *      impl.FullName());
             *
             *  return DifferenceType.Changed;
             * }
             */

            if (isContractOverridable && !isImplOverridable)
            {
                differences.AddIncompatibleDifference("CannotMakeMemberNonVirtual", impl.GetMemberViolationMessage("Member", $"is non-virtual in the {Implementation}", $"is virtual in the {Contract}"));
                return(DifferenceType.Changed);
            }

            return(DifferenceType.Unknown);
        }
예제 #3
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (impl == null || contract == null)
            {
                return(DifferenceType.Unknown);
            }

            if (impl.IsAbstract() && !contract.IsAbstract())
            {
                differences.AddIncompatibleDifference("CannotMakeMemberAbstract", impl.GetMemberViolationMessage("Member", $"is abstract in the {Implementation}", $"is not abstract in the {Contract}"));
                return(DifferenceType.Changed);
            }

            return(DifferenceType.Unknown);
        }
예제 #4
0
        public override DifferenceType Diff(IDifferences differences, MemberMapping mapping)
        {
            ITypeDefinitionMember implMember     = mapping[0];
            ITypeDefinitionMember contractMember = mapping[1];

            if (!(implMember == null && contractMember != null))
            {
                return(DifferenceType.Unknown);
            }

            // Nested types are handled separately.
            // @TODO: Events and Properties - should we consider these too (or rely on the fact that dropping one of these will also drop their accessors.)
            if (!(contractMember is IMethodDefinition || contractMember is IFieldDefinition))
            {
                return(DifferenceType.Unknown);
            }

            string incompatibleDifferenceMessage = contractMember.GetMemberViolationMessage("Member", $"does not exist in the {Implementation}", $"it does exist in the {Contract}");

            ITypeDefinition contractType = mapping.ContainingType[0];

            if (contractType != null)
            {
                if (contractMember is IMethodDefinition contractMethod)
                {
                    // If the contract is a Explicit Interface method, we don't need to check if the method is in implementation since that will be caught by different rule.
                    if (contractMethod.IsExplicitInterfaceMethod())
                    {
                        return(DifferenceType.Unknown);
                    }

                    // It is valid to promote a member from a base type up so check to see if it member exits on a base type.
                    if (FindMatchingMethodOnBase(contractType, contractMethod))
                    {
                        return(DifferenceType.Unknown);
                    }
                }
            }

            differences.AddIncompatibleDifference(this, incompatibleDifferenceMessage);
            return(DifferenceType.Added);
        }
예제 #5
0
        public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract)
        {
            if (contract != null && impl == null)
            {
                if (contract.ContainingTypeDefinition.IsInterface)
                {
                    differences.AddIncompatibleDifference(this, contract.GetMemberViolationMessage($"{GetNameOfInterfaceMemberType(contract)}", $"is present in the {Contract}", $"not in the {Implementation}"));
                    return(DifferenceType.Changed);
                }
            }

            if (impl != null && contract == null)
            {
                if (impl.ContainingTypeDefinition.IsInterface && !CanIgnoreAddedInterfaceMember(impl))
                {
                    differences.AddIncompatibleDifference(this, impl.GetMemberViolationMessage($"{GetNameOfInterfaceMemberType(impl)}", $"is present in the {Implementation}", $"not in the {Contract}"));
                    return(DifferenceType.Changed);
                }
            }

            return(base.Diff(differences, impl, contract));
        }