public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract) { if (impl == null || contract == null) { return(DifferenceType.Unknown); } // If implementation is public then contract can be any visibility if (impl.Visibility == TypeMemberVisibility.Public) { return(DifferenceType.Unknown); } // If implementation is protected or protected internal then contract must be protected or protected internal as well. if (impl.Visibility == TypeMemberVisibility.Family || impl.Visibility == TypeMemberVisibility.FamilyOrAssembly) { if (contract.Visibility != TypeMemberVisibility.Family && contract.Visibility != TypeMemberVisibility.FamilyOrAssembly) { differences.AddIncompatibleDifference(this, $"Visibility of member '{impl.FullName()}' is '{impl.Visibility}' in the {Implementation} but '{contract.Visibility}' 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", "Member '{0}' is non-virtual in the implementation but is virtual in the contract.", impl.FullName()); 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", $"Member '{impl.FullName()}' is non-virtual in the {Implementation} but is virtual in the {Contract}."); return(DifferenceType.Changed); } return(DifferenceType.Unknown); }
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, "Member '{0}' is abstract in the implementation but is missing in the contract.", impl.FullName()); 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 implementation is public then contract can be any visibility if (impl.Visibility == TypeMemberVisibility.Public) { return(DifferenceType.Unknown); } // If implementation is protected then contract must be protected as well. if (impl.Visibility == TypeMemberVisibility.Family) { if (contract.Visibility != TypeMemberVisibility.Family) { differences.AddIncompatibleDifference(this, "Visibility of member '{0}' is '{1}' in the implementation but '{2}' in the contract.", impl.FullName(), impl.Visibility, contract.Visibility); return(DifferenceType.Changed); } } return(DifferenceType.Unknown); }
private static ExceptionInfo ScanPlatformNotSupported(ITypeDefinitionMember item) { if (item is IMethodDefinition m) { if (m.IsPropertyOrEventAccessor()) { return(ExceptionInfo.DoesNotThrow); } return(ScanPlatformNotSupported(m)); } else if (item is IPropertyDefinition p) { return(ScanPlatformNotSupported(p.Accessors)); } else if (item is IEventDefinition e) { return(ScanPlatformNotSupported(e.Accessors)); } else if (item is IFieldDefinition || item is ITypeDefinition) { // Ignore return(ExceptionInfo.DoesNotThrow); } else { throw new NotImplementedException($"Unexpected type member: {item.FullName()} ({item.GetApiKind()})"); } }
public override DifferenceType Diff(IDifferences differences, MemberMapping mapping) { ITypeDefinitionMember implMember = mapping[0]; ITypeDefinitionMember contractMember = mapping[1]; IMethodDefinition foundMethod; 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 incompatibeDifferenceMessage = $"Member '{contractMember.FullName()}' does not exist in the {Implementation} but it does exist in the {Contract}."; ITypeDefinition contractType = mapping.ContainingType[0]; if (contractType != null) { IMethodDefinition contractMethod = contractMember as IMethodDefinition; if (contractMethod != null) { // 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. var lookForMethodInBaseResult = FindMatchingBase(contractType, contractMethod, out foundMethod); if (lookForMethodInBaseResult == FindMethodResult.Found) { return(DifferenceType.Unknown); } if (lookForMethodInBaseResult == FindMethodResult.ReturnTypeChanged) { incompatibeDifferenceMessage += $" There does exist a member with return type '{foundMethod.GetReturnType().FullName()}' instead of '{contractMethod.GetReturnType().FullName()}'"; } } } differences.AddIncompatibleDifference(this, incompatibeDifferenceMessage); return(DifferenceType.Added); }
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", "Member '{0}' is abstract in the implementation but is not abstract in the contract.", impl.FullName()); return DifferenceType.Changed; } return DifferenceType.Unknown; }
private bool IsDeprecated(ITypeDefinitionMember item) { if (item is IMethodDefinition m) { return(CheckMethodForDeprecation(m)); } else if (item is IFieldDefinition || item is ITypeDefinition) { // Ignore return(false); } else { throw new NotImplementedException($"Unexpected type member: {item.FullName()} ({item.GetApiKind()})"); } }
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", $"Member '{impl.FullName()}' is abstract in the {Implementation} but is not abstract in the {Contract}."); return(DifferenceType.Changed); } return(DifferenceType.Unknown); }
public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract) { if (contract != null && impl == null) { if (contract.ContainingTypeDefinition.IsInterface) { differences.AddIncompatibleDifference(this, $"Interface member '{contract.FullName()}' is present in the {Contract} but not in the {Implementation}."); return(DifferenceType.Changed); } } if (impl != null && contract == null) { if (impl.ContainingTypeDefinition.IsInterface && !CanIgnoreAddedInterfaceMember(impl)) { differences.AddIncompatibleDifference(this, $"Interface member '{impl.FullName()}' is present in the {Implementation} but not in the {Contract}."); return(DifferenceType.Changed); } } return(base.Diff(differences, impl, contract)); }
public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract) { if (contract != null && impl == null) { if (contract.ContainingTypeDefinition.IsInterface) { differences.AddIncompatibleDifference(this, "Contract interface member '{0}' is not in the implementation.", contract.FullName()); return DifferenceType.Changed; } } if (impl != null && contract == null) { if (impl.ContainingTypeDefinition.IsInterface) { differences.AddIncompatibleDifference(this, "Implementation interface member '{0}' is not in the contract.", impl.FullName()); return DifferenceType.Changed; } } return base.Diff(differences, impl, contract); }
public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract) { if (impl == null || contract == null) return DifferenceType.Unknown; // If implementation is public then contract can be any visibility if (impl.Visibility == TypeMemberVisibility.Public) return DifferenceType.Unknown; // If implementation is protected then contract must be protected as well. if (impl.Visibility == TypeMemberVisibility.Family) { if (contract.Visibility != TypeMemberVisibility.Family) { differences.AddIncompatibleDifference(this, "Visibility of member '{0}' is '{1}' in the implementation but '{2}' in the contract.", impl.FullName(), impl.Visibility, contract.Visibility); return DifferenceType.Changed; } } return DifferenceType.Unknown; }
public override DifferenceType Diff(IDifferences differences, ITypeDefinitionMember impl, ITypeDefinitionMember contract) { if (contract != null && impl == null) { if (contract.ContainingTypeDefinition.IsInterface) { differences.AddIncompatibleDifference(this, "Contract interface member '{0}' is not in the implementation.", contract.FullName()); return(DifferenceType.Changed); } } if (impl != null && contract == null) { if (impl.ContainingTypeDefinition.IsInterface) { differences.AddIncompatibleDifference(this, "Implementation interface member '{0}' is not in the contract.", impl.FullName()); return(DifferenceType.Changed); } } return(base.Diff(differences, impl, contract)); }