public override bool Equals(XElement source, XElement target, ApiChanges changes) { if (base.Equals(source, target, changes)) { return(true); } var change = new ApiChange(GetDescription(source), State); change.Header = "Modified " + GroupName; change.Append("public event "); var srcEventType = source.GetTypeName("eventtype", State); var tgtEventType = target.GetTypeName("eventtype", State); if (srcEventType != tgtEventType) { change.AppendModified(srcEventType, tgtEventType, true); } else { change.Append(srcEventType); } change.Append(" "); change.Append(source.GetAttribute("name")).Append(";"); return(false); }
protected void RenderVisibility(MethodAttributes source, MethodAttributes target, ApiChange diff) { source = source & MethodAttributes.MemberAccessMask; target = target & MethodAttributes.MemberAccessMask; if (source == target) { diff.Append(GetVisibility(target)); } else { var breaking = false; switch (source) { case MethodAttributes.Private: case MethodAttributes.Assembly: case MethodAttributes.FamANDAssem: break; // these are not publicly visible, thus not breaking case MethodAttributes.FamORAssem: case MethodAttributes.Family: switch (target) { case MethodAttributes.Public: // to public is not a breaking change break; case MethodAttributes.Family: case MethodAttributes.FamORAssem: // not a breaking change, but should still show up in diff break; default: // anything else is a breaking change breaking = true; break; } break; case MethodAttributes.Public: default: // any change from public is breaking. breaking = true; break; } diff.AppendModified(GetVisibility(source), GetVisibility(target), breaking); } diff.Append(" "); }
void RenderPropertyType(XElement source, XElement target, ApiChange change) { var srcType = source.GetTypeName("ptype", State); var tgtType = target.GetTypeName("ptype", State); if (srcType == tgtType) { change.Append(tgtType); } else { change.AppendModified(srcType, tgtType, true); } change.Append(" "); }
void RenderReturnType(XElement source, XElement target, ApiChange change) { var srcType = source.GetTypeName("returntype", State); var tgtType = target.GetTypeName("returntype", State); if (srcType != tgtType) { change.AppendModified(srcType, tgtType, true); change.Append(" "); } else if (srcType != null) { // ctor don't have a return type change.Append(srcType); change.Append(" "); } }
protected void RenderGenericParameters(XElement source, XElement target, ApiChange change) { var src = source.DescendantList("generic-parameters", "generic-parameter"); var tgt = target.DescendantList("generic-parameters", "generic-parameter"); var srcCount = src == null ? 0 : src.Count; var tgtCount = tgt == null ? 0 : tgt.Count; if (srcCount == 0 && tgtCount == 0) { return; } change.Append(Formatter.LesserThan); for (int i = 0; i < System.Math.Max(srcCount, tgtCount); i++) { if (i > 0) { change.Append(", "); } if (i >= srcCount) { change.AppendAdded(RenderGenericParameter(tgt [i]), true); } else if (i >= tgtCount) { change.AppendRemoved(RenderGenericParameter(src [i]), true); } else { var srcName = RenderGenericParameter(src [i]); var tgtName = RenderGenericParameter(tgt [i]); if (srcName != tgtName) { change.AppendModified(srcName, tgtName, true); } else { change.Append(srcName); } } } change.Append(Formatter.GreaterThan); }
protected void RenderName(XElement source, XElement target, ApiChange change) { var name = target.GetAttribute("name"); // show the constructor as it would be defined in C# name = name.Replace(".ctor", State.Type); var p = name.IndexOf('('); if (p >= 0) { name = name.Substring(0, p); } change.Append(name); }
void RenderAccessors(XElement srcGetter, XElement tgtGetter, XElement srcSetter, XElement tgtSetter, ApiChange change) { // FIXME: this doesn't render changes in the accessor visibility (a protected setter can become public for instance). change.Append(" {"); if (tgtGetter != null) { if (srcGetter != null) { change.Append(" ").Append("get;"); } else { change.Append(" ").AppendAdded("get;"); } } else if (srcGetter != null) { change.Append(" ").AppendRemoved("get;"); } if (tgtSetter != null) { if (srcSetter != null) { change.Append(" ").Append("set;"); } else { change.Append(" ").AppendAdded("set;"); } } else if (srcSetter != null) { change.Append(" ").AppendRemoved("set;"); } change.Append(" }"); // Ignore added property setters if asked to if (srcSetter == null && tgtSetter != null && State.IgnoreAddedPropertySetters && !change.Breaking) { change.AnyChange = false; change.HasIgnoredChanges = true; } }
void RenderIndexers(List <XElement> srcIndexers, List <XElement> tgtIndexers, ApiChange change) { change.Append("this ["); for (int i = 0; i < srcIndexers.Count; i++) { var source = srcIndexers [i]; var target = tgtIndexers [i]; if (i > 0) { change.Append(", "); } var srcType = source.GetTypeName("type", State); var tgtType = target.GetTypeName("type", State); if (srcType == tgtType) { change.Append(tgtType); } else { change.AppendModified(srcType, tgtType, true); } change.Append(" "); var srcName = source.GetAttribute("name"); var tgtName = target.GetAttribute("name"); if (srcName == tgtName) { change.Append(tgtName); } else { change.AppendModified(srcName, tgtName, true); } } change.Append("]"); }
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) { if (State.IgnoreVirtualChanges) { change.HasIgnoredChanges = true; } else { 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 { if (srcVirtual && !tgtVirtual && State.IgnoreVirtualChanges) { change.HasIgnoredChanges = true; } 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 < System.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", State) + " " + tgt [i].GetAttribute("name"), true); } else if (i >= tgtCount) { change.AppendRemoved(mods_src + src [i].GetTypeName("type", State) + " " + src [i].GetAttribute("name"), true); } else { var paramSourceType = src [i].GetTypeName("type", State); var paramTargetType = tgt [i].GetTypeName("type", State); 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(")"); }
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]{Environment.NewLine}"); } else { change.AppendAdded($"[NonSerialized]{Environment.NewLine}"); } } } // 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(" "); } }
public override bool Equals(XElement source, XElement target, ApiChanges changes) { if (base.Equals(source, target, changes)) { return(true); } var name = source.GetAttribute("name"); var srcValue = source.GetAttribute("value"); var tgtValue = target.GetAttribute("value"); var change = new ApiChange(GetDescription(source), State); change.Header = "Modified " + GroupName; if (State.BaseType == "System.Enum") { change.Append(name).Append(" = "); if (srcValue != tgtValue) { change.AppendModified(srcValue, tgtValue, true); } else { change.Append(srcValue); } } else { RenderFieldAttributes(source.GetFieldAttributes(), target.GetFieldAttributes(), change); var srcType = source.GetTypeName("fieldtype", State); var tgtType = target.GetTypeName("fieldtype", State); if (srcType != tgtType) { change.AppendModified(srcType, tgtType, true); } else { change.Append(srcType); } change.Append(" "); change.Append(name); if (srcType == "string" && srcValue != null) { srcValue = "\"" + srcValue + "\""; } if (tgtType == "string" && tgtValue != null) { tgtValue = "\"" + tgtValue + "\""; } if (srcValue != tgtValue) { change.Append(" = "); if (srcValue == null) { srcValue = "null"; } if (tgtValue == null) { tgtValue = "null"; } change.AppendModified(srcValue, tgtValue, true); } else if (srcValue != null) { change.Append(" = "); change.Append(srcValue); } change.Append(";"); } changes.Add(source, target, change); return(false); }