Skip to content

Commit acbdafe

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

File tree

11 files changed

+527
-11
lines changed

11 files changed

+527
-11
lines changed

mdoc/Mono.Documentation/MDocUpdater.cs

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,8 +1493,8 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
14931493
{
14941494
Console.WriteLine (message + ": " + type.FullName);
14951495
StringToXmlNodeMap seenmembers = new StringToXmlNodeMap ();
1496-
StringToXmlNodeMap seenmembersdocid = new StringToXmlNodeMap();
1497-
1496+
StringToXmlNodeMap seenmembersdocid = new StringToXmlNodeMap();
1497+
var allTypeEiimembers = GetTypeEiiMembers(type);
14981498
// Update type metadata
14991499
UpdateType (basefile.DocumentElement, type, typeEntry);
15001500

@@ -1649,7 +1649,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
16491649
}
16501650

16511651
// Update signature information
1652-
UpdateMember (info, typeEntry, implementedMembers);
1652+
UpdateMember (info, typeEntry, implementedMembers, allTypeEiimembers);
16531653
memberSet.Add (info.Member.FullName);
16541654

16551655
// get all apistyles of sig from info.Node
@@ -1707,7 +1707,7 @@ public void DoUpdateType2 (string message, XmlDocument basefile, TypeDefinition
17071707
.ToArray();
17081708
foreach (MemberReference m in typemembers)
17091709
{
1710-
XmlElement mm = MakeMember (basefile, new DocsNodeInfo (null, m), members, typeEntry, implementedMembers);
1710+
XmlElement mm = MakeMember (basefile, new DocsNodeInfo (null, m), members, typeEntry, implementedMembers, allTypeEiimembers);
17111711
if (mm == null) continue;
17121712

17131713
if (MDocUpdater.SwitchingToMagicTypes || MDocUpdater.HasDroppedNamespace (m))
@@ -2400,7 +2400,7 @@ internal static IEnumerable<T> Sort<T> (IEnumerable<T> list)
24002400
return l;
24012401
}
24022402

2403-
private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> implementedMembers)
2403+
private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> implementedMembers, IEnumerable<Eiimembers> eiiMenbers)
24042404
{
24052405
XmlElement me = (XmlElement)info.Node;
24062406
MemberReference mi = info.Member;
@@ -2411,7 +2411,7 @@ private void UpdateMember (DocsNodeInfo info, FrameworkTypeEntry typeEntry, Dict
24112411
me.SetAttribute ("MemberName", memberName);
24122412

24132413
WriteElementText (me, "MemberType", GetMemberType (mi));
2414-
AddImplementedMembers(typeEntry, mi, implementedMembers, me);
2414+
AddImplementedMembers(typeEntry, mi, implementedMembers, me, eiiMenbers);
24152415

24162416
if (!no_assembly_versions)
24172417
{
@@ -2703,7 +2703,7 @@ private static void GetUpdateXmlMethods(MemberFormatter formatter, XmlElement xm
27032703
}
27042704

27052705

2706-
private static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberReference mi, Dictionary<string, List<MemberReference>> allImplementedMembers, XmlElement root)
2706+
public static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberReference mi, Dictionary<string, List<MemberReference>> allImplementedMembers, XmlElement root, IEnumerable<Eiimembers> eiiMembers)
27072707
{
27082708
if (typeEntry.TimesProcessed > 1)
27092709
return;
@@ -2742,6 +2742,45 @@ private static void AddImplementedMembers(FrameworkTypeEntry typeEntry, MemberRe
27422742
}
27432743
}
27442744

2745+
if (!isExplicitlyImplemented)
2746+
{
2747+
eiiMembers.Where(x => x.Fingerprint == fingerprint).ToList().ForEach(t =>
2748+
{
2749+
t.Interfaces.ForEach(u =>
2750+
{
2751+
var delitem = implementedMembers.FirstOrDefault(i =>
2752+
{
2753+
if (mi is MethodDefinition)
2754+
{
2755+
MethodDefinition methodDefinition = (MethodDefinition)i;
2756+
if (methodDefinition.FullName == u.FullName)
2757+
return true;
2758+
}
2759+
2760+
if (mi is PropertyDefinition)
2761+
{
2762+
PropertyDefinition propertyDefinition = (PropertyDefinition)i;
2763+
if (propertyDefinition.GetMethod?.FullName == u.FullName
2764+
|| propertyDefinition.SetMethod?.FullName == u.FullName)
2765+
return true;
2766+
}
2767+
2768+
if (mi is EventDefinition)
2769+
{
2770+
EventDefinition evendDefinition = (EventDefinition)i;
2771+
if (evendDefinition.AddMethod?.FullName == u.FullName
2772+
|| evendDefinition.RemoveMethod?.FullName == u.FullName)
2773+
return true;
2774+
}
2775+
return false;
2776+
});
2777+
2778+
if (delitem != null)
2779+
implementedMembers.Remove(delitem);
2780+
});
2781+
});
2782+
}
2783+
27452784
if (!implementedMembers.Any())
27462785
return;
27472786

@@ -4201,7 +4240,7 @@ private void MakeReturnValue (FrameworkTypeEntry typeEntry, XmlElement root, Mem
42014240
throw new ArgumentException (mi + " is a " + mi.GetType ().FullName);
42024241
}
42034242

4204-
private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode members, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> iplementedMembers)
4243+
private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode members, FrameworkTypeEntry typeEntry, Dictionary<string, List<MemberReference>> iplementedMembers, IEnumerable<Eiimembers> eiiMenbers)
42054244
{
42064245
MemberReference mi = info.Member;
42074246
if (mi is TypeDefinition) return null;
@@ -4220,7 +4259,7 @@ private XmlElement MakeMember (XmlDocument doc, DocsNodeInfo info, XmlNode membe
42204259
AddEiiNameAsAttribute(mi, me, memberName);
42214260

42224261
info.Node = me;
4223-
UpdateMember (info, typeEntry, iplementedMembers);
4262+
UpdateMember (info, typeEntry, iplementedMembers, eiiMenbers);
42244263
if (exceptions.HasValue &&
42254264
(exceptions.Value & ExceptionLocations.AddedMembers) != 0)
42264265
UpdateExceptions (info.Node, info.Member);
@@ -4420,6 +4459,32 @@ public static string GetXPathForMember (MemberReference member)
44204459
private static IEnumerable<XmlElement> QueryXmlElementsByXpath(XmlElement parentNode, string xPath)
44214460
{
44224461
return parentNode.SelectNodes(xPath).SafeCast<XmlElement>().ToArray();
4462+
}
4463+
4464+
public static IEnumerable<Eiimembers> GetTypeEiiMembers(TypeDefinition type)
4465+
{
4466+
if (!DocUtils.IsDelegate(type))
4467+
{
4468+
var eiiTypeMembers = type.GetMembers()
4469+
.Where(m =>
4470+
{
4471+
if (m is TypeDefinition) return false;
4472+
string cssig = FormatterManager.MemberFormatters[0].GetDeclaration(m);
4473+
if (cssig == null) return false;
4474+
4475+
string sig = FormatterManager.MemberFormatters[1].GetDeclaration(m);
4476+
if (sig == null) return false;
4477+
4478+
if (!IsMemberNotPrivateEII(m))
4479+
return false;
4480+
return true;
4481+
})
4482+
.Where(t => DocUtils.IsExplicitlyImplemented(t))
4483+
.Select(t => new Eiimembers { Fingerprint = DocUtils.GetFingerprint(t), Interfaces = DocUtils.GetOverrides(t).ToList<MemberReference>() });
4484+
return eiiTypeMembers;
4485+
}
4486+
else
4487+
{ return new List<Eiimembers>(); }
44234488
}
44244489
}
44254490
}

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: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,62 @@ public void RemoveInvalidAssembliesInfo()
101101
// foreach (var delitem in delList)
102102
// delitem.ParentNode.RemoveChild(child);
103103
}
104+
105+
[Test]
106+
public void UpdateToRight_MethodInterface_Test()
107+
{
108+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Methods.FirstOrDefault(t => t.FullName == "System.String mdoc.Test2.EiiImplementClass::GetNo()");
109+
var nodeinfo = UpdateXml("GetNo", member);
110+
Assert.IsTrue(nodeinfo.Count() == 1);
111+
Assert.AreEqual("M:mdoc.Test2.Interface_B.GetNo", nodeinfo[0].InnerText);
112+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
113+
}
114+
115+
[Test]
116+
public void UpdateToRight_PropertyInterface_Test()
117+
{
118+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Properties.FirstOrDefault(t => t.FullName == "System.Int32 mdoc.Test2.EiiImplementClass::no()");
119+
var nodeinfo = UpdateXml("no", member);
120+
Assert.IsTrue(nodeinfo.Count() == 1);
121+
Assert.AreEqual("P:mdoc.Test2.Interface_A.no", nodeinfo[0].InnerText);
122+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
123+
}
124+
125+
[Test]
126+
public void UpdateToRight_EventInterface_Test()
127+
{
128+
var member = GetType(typeof(mdoc.Test2.EiiImplementClass)).Events.FirstOrDefault(t => t.FullName == "System.EventHandler`1<System.EventArgs> mdoc.Test2.EiiImplementClass::ItemChanged");
129+
var nodeinfo = UpdateXml("ItemChanged", member);
130+
Assert.IsTrue(nodeinfo.Count() == 1);
131+
Assert.AreEqual("E:mdoc.Test2.Interface_A.ItemChanged", nodeinfo[0].InnerText);
132+
Assert.AreEqual("dotnet-plat-ext-2.2", nodeinfo[0].GetAttribute(Consts.FrameworkAlternate));
133+
}
134+
135+
private List<XmlElement> UpdateXml(string XmlNodeName, MemberReference mi)
136+
{
137+
List<XmlElement> returnValue = new List<XmlElement>();
138+
139+
List<FrameworkEntry> entries = new List<FrameworkEntry>();
140+
FrameworkEntry singleEntry = new FrameworkEntry(entries, entries);
141+
singleEntry.Name = "dotnet-plat-ext-2.2";
142+
FrameworkTypeEntry enttyType = new FrameworkTypeEntry(singleEntry);
143+
144+
var type = GetType(typeof(mdoc.Test2.EiiImplementClass));
145+
var ieeImplementList = MDocUpdater.GetTypeEiiMembers(type);
146+
var typeInterfaces = GetClassInterface(type);
147+
148+
var doc = new XmlDocument();
149+
doc.LoadXml(XmlConsts.EiiErrorImplement);
150+
151+
var node = doc.SelectSingleNode($"/Type/Members/Member[@MemberName='{XmlNodeName}']");
152+
153+
if (node != null)
154+
{
155+
MDocUpdater.AddImplementedMembers(enttyType, mi, typeInterfaces, (XmlElement)node, ieeImplementList);
156+
returnValue = node.SelectNodes("Implements/InterfaceMember").Cast<XmlElement>().ToList();
157+
}
158+
159+
return returnValue;
160+
}
104161
}
105162
}
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)