Beispiel #1
0
        protected void RenderAttributes(XElement source, XElement target, ApiChanges changes)
        {
            var srcObsolete = source.GetObsoleteMessage();
            var tgtObsolete = target.GetObsoleteMessage();

            if (srcObsolete == tgtObsolete)
            {
                return;                 // nothing changed
            }
            if (srcObsolete == null)
            {
                if (tgtObsolete == null)
                {
                    return;                     // neither is obsolete
                }
                var change = new ApiChange(GetDescription(source), State);
                change.Header = "Obsoleted " + GroupName;
                Formatter.RenderObsoleteMessage(change.Member, this, GetDescription(target), tgtObsolete);
                change.AnyChange = true;
                changes.Add(source, target, change);
            }
            else if (tgtObsolete == null)
            {
                // Made non-obsolete. Do we care to report this?
            }
            else
            {
                // Obsolete message changed. Do we care to report this?
            }
        }
        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);
        }
Beispiel #3
0
 public override void Diff(TextWriter output, ApiChange apichange)
 {
     output.Write("<div {0}>", apichange.Breaking ? "data-is-breaking" : "data-is-non-breaking");
     foreach (var line in apichange.Member.ToString().Split(new[] { Environment.NewLine }, 0))
     {
         output.Write('\t');
         output.WriteLine(line);
     }
     output.Write("</div>");
 }
Beispiel #4
0
        public override void Modified(XElement source, XElement target, ApiChanges diff)
        {
            // hack - there could be changes that we're not monitoring (e.g. attributes properties)
            var output = Output;

            State.Output = new StringWriter();

            var sb = source.GetAttribute("base");
            var tb = target.GetAttribute("base");
            var rm = $"{State.Namespace}.{State.Type}: Modified base type: '{sb}' to '{tb}'";

            State.LogDebugMessage($"Possible -r value: {rm}");
            if (sb != tb &&
                !State.IgnoreRemoved.Any(re => re.IsMatch(rm)) &&
                !(State.IgnoreNonbreaking && IsBaseChangeCompatible(sb, tb)))
            {
                Formatter.BeginMemberModification(Output, "Modified base type");
                var apichange = new ApiChange($"{State.Namespace}.{State.Type}", State).AppendModified(sb, tb, true);
                Formatter.Diff(Output, apichange);
                Formatter.EndMemberModification(Output);
            }

            ccomparer.Compare(source, target);
            icomparer.Compare(source, target);
            fcomparer.Compare(source, target);
            pcomparer.Compare(source, target);
            ecomparer.Compare(source, target);
            mcomparer.Compare(source, target);

            var si = source.Element("classes");

            if (si != null)
            {
                var ti = target.Element("classes");
                kcomparer    = new NestedClassComparer(State);
                State.Parent = State.Type;
                kcomparer.Compare(si.Elements("class"), ti == null ? null : ti.Elements("class"));
                State.Type = State.Parent;
            }

            var s = (Output as StringWriter).ToString();

            State.Output = output;
            if (s.Length > 0)
            {
                SetContext(target);
                Formatter.BeginTypeModification(Output);
                Output.WriteLine(s);
                Formatter.EndTypeModification(Output);
            }
        }
Beispiel #5
0
 public override void Diff(TextWriter output, ApiChange apichange)
 {
     foreach (var line in apichange.Member.ToString().Split('\n'))
     {
         if (line.Contains("+++"))
         {
             output.WriteLine("-{0}", Clean(line, "+++", "---"));
             output.WriteLine("+{0}", Clean(line, "---", "+++"));
         }
         else
         {
             output.WriteLine(" {0}", line);
         }
     }
 }
Beispiel #6
0
        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(" ");
        }
Beispiel #7
0
        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 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(" ");
            }
        }
Beispiel #9
0
        protected void RenderStatic(MethodAttributes src, MethodAttributes tgt, ApiChange diff)
        {
            var srcStatic = (src & MethodAttributes.Static) == MethodAttributes.Static;
            var tgtStatic = (tgt & MethodAttributes.Static) == MethodAttributes.Static;

            if (srcStatic != tgtStatic)
            {
                if (srcStatic)
                {
                    diff.AppendRemoved("static", true).Append(" ");
                }
                else
                {
                    diff.AppendAdded("static", true).Append(" ");
                }
            }
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        public override bool Equals(XElement source, XElement target, ApiChanges changes)
        {
            if (base.Equals(source, target, changes))
            {
                return(true);
            }

            XElement srcGetter, srcSetter;
            XElement tgtGetter, tgtSetter;

            GetAccessors(source, out srcGetter, out srcSetter);
            GetAccessors(target, out tgtGetter, out tgtSetter);

            List <XElement> srcIndexers = null;
            List <XElement> tgtIndexers = null;
            bool            isIndexer   = false;

            if (srcGetter != null)
            {
                srcIndexers = srcGetter.DescendantList("parameters", "parameter");
                tgtIndexers = tgtGetter.DescendantList("parameters", "parameter");
                isIndexer   = srcIndexers != null && srcIndexers.Count > 0;
            }

            var change = new ApiChange(GetDescription(source), State);

            change.Header = "Modified " + GroupName;
            RenderMethodAttributes(GetMethodAttributes(srcGetter, srcSetter), GetMethodAttributes(tgtGetter, tgtSetter), change);
            RenderPropertyType(source, target, change);
            if (isIndexer)
            {
                RenderIndexers(srcIndexers, tgtIndexers, change);
            }
            else
            {
                RenderName(source, target, change);
            }
            RenderGenericParameters(source, target, change);
            RenderAccessors(srcGetter, tgtGetter, srcSetter, tgtSetter, change);

            changes.Add(source, target, change);

            return(false);
        }
        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;
            RenderMethodAttributes(source, target, change);
            RenderReturnType(source, target, change);
            RenderName(source, target, change);
            RenderGenericParameters(source, target, change);
            RenderParameters(source, target, change);

            changes.Add(source, target, change);

            return(false);
        }
Beispiel #13
0
 public abstract void Diff(TextWriter output, ApiChange apichange);
Beispiel #14
0
 protected void RenderMethodAttributes(XElement source, XElement target, ApiChange diff)
 {
     RenderMethodAttributes(source.GetMethodAttributes(), target.GetMethodAttributes(), diff);
 }
Beispiel #15
0
 protected void RenderMethodAttributes(MethodAttributes src, MethodAttributes tgt, ApiChange diff)
 {
     RenderStatic(src, tgt, diff);
     RenderVisibility(src & MethodAttributes.MemberAccessMask, tgt & MethodAttributes.MemberAccessMask, diff);
     RenderVTable(src, tgt, diff);
 }
Beispiel #16
0
        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(" ");
        }
Beispiel #17
0
        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;
            }
        }
Beispiel #18
0
        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(")");
        }
Beispiel #19
0
        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;
            }
        }
Beispiel #20
0
        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("]");
        }
Beispiel #21
0
        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(" ");
            }
        }
Beispiel #22
0
        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);
        }