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); }
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); }
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); }
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); }
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)); }