Skip to content

Commit 4e8dc43

Browse files
committed
[mdoc] come up with test/design for better member implementation detection
1 parent 1e6bd54 commit 4e8dc43

File tree

11 files changed

+529
-10
lines changed

11 files changed

+529
-10
lines changed

mdoc/Mono.Documentation/MDocUpdater.cs

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,7 +1604,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
16041604
Console.WriteLine (message + ": " + type.FullName);
16051605
StringToXmlNodeMap seenmembers = new StringToXmlNodeMap ();
16061606
StringToXmlNodeMap seenmembersdocid = new StringToXmlNodeMap();
1607-
1607+
var allTypeEiimembers = GetTypeEiiMembers(type);
16081608
// Update type metadata
16091609
UpdateType (basefile.DocumentElement, type, typeEntry);
16101610

@@ -1751,7 +1751,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
17511751
}
17521752

17531753
// Update signature information
1754-
UpdateMember (info, typeEntry, implementedMembers);
1754+
UpdateMember (info, typeEntry, implementedMembers, allTypeEiimembers);
17551755
memberSet.Add (info.Member.FullName);
17561756

17571757
// get all apistyles of sig from info.Node
@@ -1809,7 +1809,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
18091809
.ToArray();
18101810
foreach (MemberReference m in typemembers)
18111811
{
1812-
XmlElement mm = MakeMember (basefile, new DocsNodeInfo (null, m), members, typeEntry, implementedMembers);
1812+
XmlElement mm = MakeMember (basefile, new DocsNodeInfo (null, m), members, typeEntry, implementedMembers, allTypeEiimembers);
18131813
if (mm == null) continue;
18141814

18151815
if (MDocUpdater.SwitchingToMagicTypes || MDocUpdater.HasDroppedNamespace (m))
@@ -2494,7 +2494,7 @@ internal static IEnumerable<T> Sort<T> (IEnumerable<T> list)
24942494
return l;
24952495
}
24962496

2497-
private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> implementedMembers)
2497+
private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> implementedMembers, IEnumerable<Eiimembers> eiiMenbers)
24982498
{
24992499
XmlElement me = (XmlElement)info.Node;
25002500
MemberReference mi = info.Member;
@@ -2505,7 +2505,7 @@ private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dict
25052505
me.SetAttribute ("MemberName", memberName);
25062506

25072507
WriteElementText (me, "MemberType", GetMemberType (mi));
2508-
AddImplementedMembers(typeEntry, mi, implementedMembers, me);
2508+
AddImplementedMembers(typeEntry, mi, implementedMembers, me, eiiMenbers);
25092509

25102510
if (!no_assembly_versions)
25112511
{
@@ -2797,7 +2797,7 @@ private static void GetUpdateXmlMethods(MemberFormatter formatter, XmlElement xm
27972797
}
27982798

27992799

2800-
private static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberReference mi, Dictionary<string, List<MemberReference>> allImplementedMembers, XmlElement root)
2800+
public static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberReference mi, Dictionary<string, List<MemberReference>> allImplementedMembers, XmlElement root, IEnumerable<Eiimembers> eiiMembers)
28012801
{
28022802
if (typeEntry.TimesProcessed > 1)
28032803
return;
@@ -2836,6 +2836,45 @@ private static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberRe
28362836
}
28372837
}
28382838

2839+
if (!isExplicitlyImplemented)
2840+
{
2841+
eiiMembers.Where(x => x.Fingerprint == fingerprint).ToList().ForEach(t =>
2842+
{
2843+
t.Interfaces.ForEach(u =>
2844+
{
2845+
var delitem = implementedMembers.FirstOrDefault(i =>
2846+
{
2847+
if (mi is MethodDefinition)
2848+
{
2849+
MethodDefinition methodDefinition = (MethodDefinition)i;
2850+
if (methodDefinition.FullName == u.FullName)
2851+
return true;
2852+
}
2853+
2854+
if (mi is PropertyDefinition)
2855+
{
2856+
PropertyDefinition propertyDefinition = (PropertyDefinition)i;
2857+
if (propertyDefinition.GetMethod?.FullName == u.FullName
2858+
|| propertyDefinition.SetMethod?.FullName == u.FullName)
2859+
return true;
2860+
}
2861+
2862+
if (mi is EventDefinition)
2863+
{
2864+
EventDefinition evendDefinition = (EventDefinition)i;
2865+
if (evendDefinition.AddMethod?.FullName == u.FullName
2866+
|| evendDefinition.RemoveMethod?.FullName == u.FullName)
2867+
return true;
2868+
}
2869+
return false;
2870+
});
2871+
2872+
if (delitem != null)
2873+
implementedMembers.Remove(delitem);
2874+
});
2875+
});
2876+
}
2877+
28392878
if (!implementedMembers.Any())
28402879
return;
28412880

@@ -4463,7 +4502,7 @@ private void MakeReturnValue (FrameworkTypeEntry typeEntry, XmlElement root, Mem
44634502
throw new ArgumentException (mi + " is a " + mi.GetType ().FullName);
44644503
}
44654504

4466-
private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode members, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> iplementedMembers)
4505+
private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode members, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> iplementedMembers, IEnumerable<Eiimembers> eiiMenbers)
44674506
{
44684507
MemberReference mi = info.Member;
44694508
if (mi is TypeDefinition) return null;
@@ -4482,7 +4521,7 @@ private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode membe
44824521
AddEiiNameAsAttribute(mi, me, memberName);
44834522

44844523
info.Node = me;
4485-
UpdateMember (info, typeEntry, iplementedMembers);
4524+
UpdateMember (info, typeEntry, iplementedMembers, eiiMenbers);
44864525
if (exceptions.HasValue &&
44874526
(exceptions.Value & ExceptionLocations.AddedMembers) != 0)
44884527
UpdateExceptions (info.Node, info.Member);
@@ -4682,6 +4721,32 @@ public static string GetXPathForMember (MemberReference member)
46824721
private static IEnumerable<XmlElement> QueryXmlElementsByXpath(XmlElement parentNode, string xPath)
46834722
{
46844723
return parentNode.SelectNodes(xPath).SafeCast<XmlElement>().ToArray();
4724+
}
4725+
4726+
public static IEnumerable<Eiimembers> GetTypeEiiMembers(TypeDefinition type)
4727+
{
4728+
if (!DocUtils.IsDelegate(type))
4729+
{
4730+
var eiiTypeMembers = type.GetMembers()
4731+
.Where(m =>
4732+
{
4733+
if (m is TypeDefinition) return false;
4734+
string cssig = memberFormatters[0].GetDeclaration(m);
4735+
if (cssig == null) return false;
4736+
4737+
string sig = memberFormatters[1].GetDeclaration(m);
4738+
if (sig == null) return false;
4739+
4740+
if (!IsMemberNotPrivateEII(m))
4741+
return false;
4742+
return true;
4743+
})
4744+
.Where(t => DocUtils.IsExplicitlyImplemented(t))
4745+
.Select(t => new Eiimembers { Fingerprint = DocUtils.GetFingerprint(t), Interfaces = DocUtils.GetOverrides(t).ToList<MemberReference>() });
4746+
return eiiTypeMembers;
4747+
}
4748+
else
4749+
{ return new List<Eiimembers>(); }
46854750
}
46864751
}
46874752
}

mdoc/Mono.Documentation/Updater/DocUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,7 @@ public static bool IsExplicitlyImplemented(MemberReference memberReference)
796796
/// <summary>
797797
/// Get which members are overriden by memberReference
798798
/// </summary>
799-
private static Collection<MethodReference> GetOverrides(MemberReference memberReference)
799+
public static Collection<MethodReference> GetOverrides(MemberReference memberReference)
800800
{
801801
if (memberReference is MethodDefinition)
802802
{
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Collections.Generic;
2+
using Mono.Cecil;
3+
namespace Mono.Documentation.Util
4+
{
5+
public class Eiimembers
6+
{
7+
public string Fingerprint { get; set; }
8+
public List<MemberReference> Interfaces { get; set; }
9+
}
10+
}

mdoc/Test/en.expected.members-implementation/TestInterfaceImplementation/Class2_1.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
<MemberType>Method</MemberType>
4444
<Implements>
4545
<InterfaceMember>M:TestInterfaceImplementation.Interface2.Method(System.Int32)</InterfaceMember>
46-
<InterfaceMember>M:TestInterfaceImplementation.Interface3.Method(System.Int32)</InterfaceMember>
4746
<InterfaceMember>M:TestInterfaceImplementation.Interface3_1.Method(System.Int32)</InterfaceMember>
4847
</Implements>
4948
<AssemblyInfo>

mdoc/mdoc.Test/MDocUpdaterTests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,65 @@ public void InternalEIITest()
7676
Assert.AreEqual("System.String mdoc.Test2.InternalEIICalss::mdoc.Test.SampleClasses.InterfaceA.Getstring(System.Int32)", oldmember.FullName);
7777

7878
}
79+
80+
[Test]
81+
public void UpdateToRight_MethodInterface_Test()
82+
{
83+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Methods.FirstOrDefault(t => t.FullName == "System.String mdoc.Test2.EiiImplementClass::GetNo()");
84+
var nodeinfo = UpdateXml("GetNo", member);
85+
Assert.IsTrue(nodeinfo.Count() == 1);
86+
Assert.AreEqual("M:mdoc.Test2.Interface_B.GetNo", nodeinfo[0].InnerText);
87+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
88+
}
89+
90+
[Test]
91+
public void UpdateToRight_PropertyInterface_Test()
92+
{
93+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Properties.FirstOrDefault(t => t.FullName == "System.Int32 mdoc.Test2.EiiImplementClass::no()");
94+
var nodeinfo = UpdateXml("no", member);
95+
Assert.IsTrue(nodeinfo.Count() == 1);
96+
Assert.AreEqual("P:mdoc.Test2.Interface_A.no", nodeinfo[0].InnerText);
97+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
98+
}
99+
100+
[Test]
101+
public void UpdateToRight_EventInterface_Test()
102+
{
103+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Events.FirstOrDefault(t => t.FullName == "System.EventHandler`1<System.EventArgs> mdoc.Test2.EiiImplementClass::ItemChanged");
104+
var nodeinfo = UpdateXml("ItemChanged", member);
105+
Assert.IsTrue(nodeinfo.Count() == 1);
106+
Assert.AreEqual("E:mdoc.Test2.Interface_A.ItemChanged", nodeinfo[0].InnerText);
107+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
108+
}
109+
110+
private List<XmlElement> UpdateXml(string XmlNodeName, MemberReference mi)
111+
{
112+
List<XmlElement> returnValue = new List<XmlElement>();
113+
114+
List<FrameworkEntry> entries = new List<FrameworkEntry>();
115+
FrameworkEntry singleEntry = new FrameworkEntry(entries, entries);
116+
singleEntry.Name = "dotnet-plat-ext-2.2";
117+
FrameworkTypeEntry enttyType = new FrameworkTypeEntry(singleEntry);
118+
119+
var type = GetType(typeof(mdoc.Test2.EiiImplementClass));
120+
var ieeImplementList = MDocUpdater.GetTypeEiiMembers(type);
121+
var typeInterfaces = GetClassInterface(type);
122+
123+
var doc = new XmlDocument();
124+
doc.LoadXml(XmlConsts.EiiErrorImplement);
125+
126+
var node = doc.SelectSingleNode($"/Type/Members/Member[@MemberName='{XmlNodeName}']");
127+
128+
if (node != null)
129+
{
130+
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Static;
131+
MethodInfo mInfo = typeof(MDocUpdater).GetMethod("AddImplementedMembers", flags); //FrameworkTypeEntry.Empty
132+
MDocUpdater.AddImplementedMembers(enttyType, mi, typeInterfaces, (XmlElement)node, ieeImplementList );
133+
134+
returnValue = node.SelectNodes("Implements/InterfaceMember").Cast<XmlElement>().ToList();
135+
}
136+
137+
return returnValue;
138+
}
79139
}
80140
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace mdoc.Test2
8+
{
9+
public class EiiImplementClass : Interface_A,Interface_B
10+
{
11+
public event EventHandler<EventArgs> ItemChanged;
12+
public string color { get; set; }
13+
14+
public int GetNum() => 3;
15+
16+
public int no { get; }
17+
int Interface_B.no { get; }
18+
19+
public string GetNo() => "1";
20+
string Interface_A.GetNo() => "7";
21+
22+
public bool IsNum(string no) => false;
23+
bool Interface_B.IsNum(string no) => true;
24+
25+
protected virtual void OnItemChanged(EventArgs e)
26+
{ }
27+
28+
event EventHandler<EventArgs> Interface_B.ItemChanged
29+
{
30+
add { }
31+
remove { }
32+
}
33+
34+
}
35+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace mdoc.Test2
8+
{
9+
public interface Interface_A
10+
{
11+
string color { get; set; }
12+
int no { get; }
13+
string GetNo();
14+
int GetNum();
15+
event EventHandler<EventArgs> ItemChanged;
16+
}
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace mdoc.Test2
8+
{
9+
public interface Interface_B
10+
{
11+
string color { get; set; }
12+
int no { get; }
13+
string GetNo();
14+
bool IsNum(string no);
15+
event EventHandler<EventArgs> ItemChanged;
16+
17+
18+
}
19+
}

0 commit comments

Comments
 (0)