void RenderVTable(MethodAttributes source, MethodAttributes target, ApiChange change) { var srcAbstract = (source & MethodAttributes.Abstract) == MethodAttributes.Abstract; var tgtAbstract = (target & MethodAttributes.Abstract) == MethodAttributes.Abstract; var srcFinal = (source & MethodAttributes.Final) == MethodAttributes.Final; var tgtFinal = (target & MethodAttributes.Final) == MethodAttributes.Final; var srcVirtual = (source & MethodAttributes.Virtual) == MethodAttributes.Virtual; var tgtVirtual = (target & MethodAttributes.Virtual) == MethodAttributes.Virtual; var srcOverride = (source & MethodAttributes.VtableLayoutMask) != MethodAttributes.NewSlot; var tgtOverride = (target & MethodAttributes.VtableLayoutMask) != MethodAttributes.NewSlot; var srcWord = srcVirtual ? (srcOverride ? "override" : "virtual") : string.Empty; var tgtWord = tgtVirtual ? (tgtOverride ? "override" : "virtual") : string.Empty; var breaking = srcWord.Length > 0 && tgtWord.Length == 0; if (srcAbstract) { if (tgtAbstract) { change.Append("abstract "); } else if (tgtVirtual) { change.AppendModified("abstract", tgtWord, false).Append(" "); } else { change.AppendRemoved("abstract").Append(" "); } } else { if (tgtAbstract) { change.AppendAdded("abstract", true).Append(" "); } else if (srcWord != tgtWord) { if (!tgtFinal) { change.AppendModified(srcWord, tgtWord, breaking).Append(" "); } } else if (tgtWord.Length > 0) { change.Append(tgtWord).Append(" "); } else if (srcWord.Length > 0) { change.AppendRemoved(srcWord, breaking).Append(" "); } } if (srcFinal) { if (tgtFinal) { change.Append("final "); } else { change.AppendRemoved("final", false).Append(" "); // removing 'final' is not a breaking change. } } else { if (tgtFinal && srcVirtual) { change.AppendModified("virtual", "final", true).Append(" "); // adding 'final' is a breaking change if the member was virtual } } if (!srcVirtual && !srcFinal && tgtVirtual && tgtFinal) { // existing member implements a member from a new interface // this would show up as 'virtual final', which is redundant, so show nothing at all. change.HasIgnoredChanges = true; } // Ignore non-breaking virtual changes. if (State.IgnoreVirtualChanges && !change.Breaking) { change.AnyChange = false; change.HasIgnoredChanges = true; } var tgtSecurity = (source & MethodAttributes.HasSecurity) == MethodAttributes.HasSecurity; var srcSecurity = (target & MethodAttributes.HasSecurity) == MethodAttributes.HasSecurity; if (tgtSecurity != srcSecurity) { change.HasIgnoredChanges = true; } var srcPInvoke = (source & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl; var tgtPInvoke = (target & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl; if (srcPInvoke != tgtPInvoke) { change.HasIgnoredChanges = true; } }
protected void RenderParameters(XElement source, XElement target, ApiChange change) { var src = source.DescendantList("parameters", "parameter"); var tgt = target.DescendantList("parameters", "parameter"); var srcCount = src == null ? 0 : src.Count; var tgtCount = tgt == null ? 0 : tgt.Count; change.Append(" ("); for (int i = 0; i < Math.Max(srcCount, tgtCount); i++) { if (i > 0) { change.Append(", "); } string mods_tgt = tgt [i].GetAttribute("direction") ?? ""; string mods_src = src [i].GetAttribute("direction") ?? ""; if (mods_tgt.Length > 0) { mods_tgt = mods_tgt + " "; } if (mods_src.Length > 0) { mods_src = mods_src + " "; } if (i >= srcCount) { change.AppendAdded(mods_tgt + tgt [i].GetTypeName("type") + " " + tgt [i].GetAttribute("name"), true); } else if (i >= tgtCount) { change.AppendRemoved(mods_src + src [i].GetTypeName("type") + " " + src [i].GetAttribute("name"), true); } else { var paramSourceType = src [i].GetTypeName("type"); var paramTargetType = tgt [i].GetTypeName("type"); var paramSourceName = src [i].GetAttribute("name"); var paramTargetName = tgt [i].GetAttribute("name"); if (mods_src != mods_tgt) { change.AppendModified(mods_src, mods_tgt, true); } else { change.Append(mods_src); } if (paramSourceType != paramTargetType) { change.AppendModified(paramSourceType, paramTargetType, true); } else { change.Append(paramSourceType); } change.Append(" "); if (!State.IgnoreParameterNameChanges && paramSourceName != paramTargetName) { change.AppendModified(paramSourceName, paramTargetName, true); } else { change.Append(paramSourceName); } var optSource = src [i].Attribute("optional"); var optTarget = tgt [i].Attribute("optional"); var srcValue = FormatValue(paramSourceType, src [i].GetAttribute("defaultValue")); var tgtValue = FormatValue(paramTargetType, tgt [i].GetAttribute("defaultValue")); if (optSource != null) { if (optTarget != null) { change.Append(" = "); if (srcValue != tgtValue) { change.AppendModified(srcValue, tgtValue, false); } else { change.Append(tgtValue); } } else { change.AppendRemoved(" = " + srcValue); } } else { if (optTarget != null) { change.AppendAdded(" = " + tgtValue); } } } } change.Append(")"); }
protected void RenderParameters(XElement source, XElement target, ApiChange change) { var src = source.DescendantList("parameters", "parameter"); var tgt = target.DescendantList("parameters", "parameter"); var srcCount = src == null ? 0 : src.Count; var tgtCount = tgt == null ? 0 : tgt.Count; change.Append(" ("); for (int i = 0; i < Math.Max(srcCount, tgtCount); i++) { if (i > 0) { change.Append(", "); } if (i >= srcCount) { change.AppendAdded(tgt [i].GetTypeName("type") + " " + tgt [i].GetAttribute("name"), true); } else if (i >= tgtCount) { change.AppendRemoved(src [i].GetTypeName("type") + " " + src [i].GetAttribute("name"), true); } else { var paramSourceType = src [i].GetTypeName("type"); var paramTargetType = tgt [i].GetTypeName("type"); var paramSourceName = src [i].GetAttribute("name"); var paramTargetName = tgt [i].GetAttribute("name"); if (paramSourceType != paramTargetType) { change.AppendModified(paramSourceType, paramTargetType, true); } else { change.Append(paramSourceType); } change.Append(" "); if (paramSourceName != paramTargetName) { change.AppendModified(paramSourceName, paramTargetName, false); } else { change.Append(paramSourceName); } var optSource = src [i].Attribute("optional"); var optTarget = tgt [i].Attribute("optional"); var srcValue = FormatValue(paramSourceType, src [i].GetAttribute("defaultValue")); var tgtValue = FormatValue(paramTargetType, tgt [i].GetAttribute("defaultValue")); if (optSource != null) { if (optTarget != null) { change.Append(" = "); if (srcValue != tgtValue) { change.AppendModified(srcValue, tgtValue, false); } else { change.Append(tgtValue); } } else { change.AppendRemoved(" = " + srcValue); } } else { if (optTarget != null) { change.AppendAdded(" = " + tgtValue); } } } } change.Append(")"); // Ignore any parameter name changes if requested. if (State.IgnoreParameterNameChanges && !change.Breaking) { change.AnyChange = false; change.HasIgnoredChanges = true; } }
void RenderFieldAttributes(FieldAttributes source, FieldAttributes target, ApiChange change) { if (!State.IgnoreNonbreaking) { var srcNotSerialized = (source & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; var tgtNotSerialized = (target & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized; if (srcNotSerialized != tgtNotSerialized) { // this is not a breaking change, so only render it if it changed. if (srcNotSerialized) { change.AppendRemoved("[NonSerialized]\n"); } else { change.AppendAdded("[NonSerialized]\n"); } } } // the visibility values are the same for MethodAttributes and FieldAttributes, so just use the same method. RenderVisibility((MethodAttributes)source, (MethodAttributes)target, change); // same for the static flag RenderStatic((MethodAttributes)source, (MethodAttributes)target, change); var srcLiteral = (source & FieldAttributes.Literal) != 0; var tgtLiteral = (target & FieldAttributes.Literal) != 0; if (srcLiteral) { if (tgtLiteral) { change.Append("const "); } else { change.AppendRemoved("const", true).Append(" "); } } else if (tgtLiteral) { change.AppendAdded("const", true).Append(" "); } var srcInitOnly = (source & FieldAttributes.InitOnly) != 0; var tgtInitOnly = (target & FieldAttributes.InitOnly) != 0; if (srcInitOnly) { if (tgtInitOnly) { change.Append("readonly "); } else { change.AppendRemoved("readonly", false).Append(" "); } } else if (tgtInitOnly) { change.AppendAdded("readonly", true).Append(" "); } }