Skip to content

Commit c4b37da

Browse files
authored
Documentation signature parser tests and fixes for NativeAOT (#79168)
This ports infra for the "MemberAssertions" tests which linker uses. It then ports the document signature parser test from linker. And adds fixes to make the tests pass. After this AOT and Linker are behaving exactly the same with regard to the tests we have for this area.
1 parent d37d3a4 commit c4b37da

File tree

6 files changed

+817
-32
lines changed

6 files changed

+817
-32
lines changed

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/DocumentationSignatureGenerator.PartVisitor.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public sealed partial class DocumentationSignatureGenerator
1717
/// Adapted from Roslyn's DocumentattionCommentIDVisitor.PartVisitor:
1818
/// https://github.com/dotnet/roslyn/blob/master/src/Compilers/CSharp/Portable/DocumentationComments/DocumentationCommentIDVisitor.PartVisitor.cs
1919
/// </summary>
20-
internal sealed class PartVisitor : TypeNameFormatter
20+
public sealed class PartVisitor : TypeNameFormatter
2121
{
22-
internal static readonly PartVisitor Instance = new PartVisitor();
22+
public static readonly PartVisitor Instance = new PartVisitor();
2323

2424
private PartVisitor()
2525
{
@@ -146,7 +146,7 @@ public override void AppendName(StringBuilder builder, GenericParameterDesc gene
146146

147147
protected override void AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType)
148148
{
149-
AppendName(sb, containingType);
149+
AppendName(sb, InstantiateContainingType(nestedType));
150150
sb.Append('.');
151151
sb.Append(nestedType.Name);
152152
}
@@ -162,10 +162,11 @@ protected override void AppendNameForNamespaceType(StringBuilder sb, DefType typ
162162
protected override void AppendNameForInstantiatedType(StringBuilder builder, DefType type)
163163
{
164164
int containingArity = 0;
165-
DefType containingType = type.ContainingType;
165+
DefType containingType = InstantiateContainingType(type);
166166
if (containingType != null)
167167
{
168168
AppendName(builder, containingType);
169+
builder.Append('.');
169170
containingArity = containingType.Instantiation.Length;
170171
}
171172
else
@@ -177,7 +178,8 @@ protected override void AppendNameForInstantiatedType(StringBuilder builder, Def
177178

178179
string unmangledName = type.Name;
179180
int totalArity = type.Instantiation.Length;
180-
string expectedSuffix = $"`{totalArity}";
181+
int nestedArity = totalArity - containingArity;
182+
string expectedSuffix = $"`{nestedArity}";
181183
if (unmangledName.EndsWith(expectedSuffix))
182184
unmangledName = unmangledName.Substring(0, unmangledName.Length - expectedSuffix.Length);
183185

@@ -218,6 +220,20 @@ private static string GetEscapedMetadataName(IMemberDefinition member)
218220
return name.Replace('<', '{').Replace('>', '}');
219221
}
220222
#endif
223+
224+
private static DefType InstantiateContainingType(DefType type)
225+
{
226+
DefType containingType = type.ContainingType;
227+
if (containingType is null)
228+
return null;
229+
230+
// If the type doesn't follow C# scheme where nested types inherit generic parameters from their container type
231+
// return the container type as-is.
232+
if (!containingType.HasInstantiation || containingType.Instantiation.Length > type.Instantiation.Length)
233+
return containingType;
234+
235+
return (DefType)containingType.InstantiateAsOpen().InstantiateSignature(type.Instantiation, default);
236+
}
221237
}
222238
}
223239
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Logging/DocumentationSignatureParser.cs

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Text;
99

1010
using Internal.TypeSystem;
11+
using Internal.TypeSystem.Ecma;
1112

1213
namespace ILCompiler.Logging
1314
{
@@ -210,21 +211,17 @@ public static void GetMatchingMembers(string id, ref int index, ModuleDesc modul
210211
index = startIndex;
211212
}
212213

213-
#if false
214214
if (memberTypes.HasFlag(MemberType.Property))
215215
{
216216
GetMatchingProperties(id, ref index, containingType, memberName, results, acceptName);
217217
endIndex = index;
218218
index = startIndex;
219219
}
220-
#endif
221220

222221
index = endIndex;
223222

224-
#if false
225223
if (memberTypes.HasFlag(MemberType.Event))
226224
GetMatchingEvents(containingType, memberName, results);
227-
#endif
228225

229226
if (memberTypes.HasFlag(MemberType.Field))
230227
GetMatchingFields(containingType, memberName, results);
@@ -536,7 +533,7 @@ private static void GetMatchingTypes(ModuleDesc module, TypeDesc declaringType,
536533
string namepart;
537534
if (indexOfLastDot > 0 && indexOfLastDot < name.Length - 1)
538535
{
539-
namespacepart = name.Substring(indexOfLastDot - 1);
536+
namespacepart = name.Substring(0, indexOfLastDot);
540537
namepart = name.Substring(indexOfLastDot + 1);
541538
}
542539
else
@@ -631,10 +628,9 @@ private static void GetMatchingMethods(string id, ref int index, TypeDesc type,
631628
index = endIndex;
632629
}
633630

634-
#if false
635-
static void GetMatchingProperties(string id, ref int index, TypeDesc type, string memberName, List<TypeSystemEntity> results, bool acceptName = false)
631+
private static void GetMatchingProperties(string id, ref int index, TypeDesc typeDesc, string memberName, List<TypeSystemEntity> results, bool acceptName = false)
636632
{
637-
if (type == null)
633+
if (typeDesc is not EcmaType type)
638634
return;
639635

640636
int startIndex = index;
@@ -643,11 +639,14 @@ static void GetMatchingProperties(string id, ref int index, TypeDesc type, strin
643639
List<string> parameters = null;
644640
// Unlike Roslyn, we don't need to decode property names because we are working
645641
// directly with IL.
646-
foreach (var property in type.Properties)
642+
foreach (var propertyHandle in type.MetadataReader.GetTypeDefinition(type.Handle).GetProperties())
647643
{
644+
var p = new PropertyPseudoDesc(type, propertyHandle);
645+
648646
index = startIndex;
649-
if (property.Name != memberName)
647+
if (p.Name != memberName)
650648
continue;
649+
651650
if (PeekNextChar(id, index) == '(')
652651
{
653652
if (parameters == null)
@@ -658,23 +657,22 @@ static void GetMatchingProperties(string id, ref int index, TypeDesc type, strin
658657
{
659658
parameters.Clear();
660659
}
661-
if (!ParseParameterList(id, ref index, property.DeclaringType, parameters))
660+
if (!ParseParameterList(id, ref index, p.OwningType, parameters))
662661
continue;
663-
if (!AllParametersMatch(property.Parameters, parameters))
662+
if (!AllParametersMatch(p.Signature, parameters))
664663
continue;
665664
}
666665
else
667666
{
668-
if (!acceptName && property.Parameters.Count != 0)
667+
if (!acceptName && p.Signature.Length != 0)
669668
continue;
670669
}
671-
results.Add(property);
670+
results.Add(p);
672671
endIndex = index;
673672
}
674673

675674
index = endIndex;
676675
}
677-
#endif
678676

679677
private static void GetMatchingFields(TypeDesc type, string memberName, List<TypeSystemEntity> results)
680678
{
@@ -688,19 +686,19 @@ private static void GetMatchingFields(TypeDesc type, string memberName, List<Typ
688686
}
689687
}
690688

691-
#if false
692-
static void GetMatchingEvents(TypeDesc type, string memberName, List<TypeSystemEntity> results)
689+
private static void GetMatchingEvents(TypeDesc typeDesc, string memberName, List<TypeSystemEntity> results)
693690
{
694-
if (type == null)
691+
if (typeDesc is not EcmaType type)
695692
return;
696-
foreach (var evt in type.Events)
693+
694+
foreach (var eventHandle in type.MetadataReader.GetTypeDefinition(type.Handle).GetEvents())
697695
{
698-
if (evt.Name != memberName)
696+
var e = new EventPseudoDesc(type, eventHandle);
697+
if (e.Name != memberName)
699698
continue;
700-
results.Add(evt);
699+
results.Add(e);
701700
}
702701
}
703-
#endif
704702

705703
private static bool AllParametersMatch(MethodSignature methodParameters, List<string> expectedParameters)
706704
{
@@ -716,6 +714,20 @@ private static bool AllParametersMatch(MethodSignature methodParameters, List<st
716714
return true;
717715
}
718716

717+
private static bool AllParametersMatch(PropertySignature propertyParameters, List<string> expectedParameters)
718+
{
719+
if (propertyParameters.Length != expectedParameters.Count)
720+
return false;
721+
722+
for (int i = 0; i < expectedParameters.Count; i++)
723+
{
724+
if (GetSignaturePart(propertyParameters[i]) != expectedParameters[i])
725+
return false;
726+
}
727+
728+
return true;
729+
}
730+
719731
private static bool ParseParameterList(string id, ref int index, TypeSystemEntity typeParameterContext, List<string> parameters)
720732
{
721733
Debug.Assert(typeParameterContext != null);

src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Collections.Generic;
55
using System.IO;
66
using System.Linq;
7+
using System.Runtime.CompilerServices;
78
using Mono.Linker.Tests.Extensions;
89
using Mono.Linker.Tests.TestCasesRunner;
910

@@ -15,17 +16,17 @@ public static class TestDatabase
1516

1617
public static IEnumerable<object[]> DataFlow ()
1718
{
18-
return TestNamesBySuiteName ("DataFlow");
19+
return TestNamesBySuiteName ();
1920
}
2021

2122
public static IEnumerable<object[]> Repro ()
2223
{
23-
return TestNamesBySuiteName ("Repro");
24+
return TestNamesBySuiteName ();
2425
}
2526

2627
public static IEnumerable<object[]> RequiresCapability ()
2728
{
28-
return TestNamesBySuiteName ("RequiresCapability");
29+
return TestNamesBySuiteName ();
2930
}
3031

3132
public static TestCaseCollector CreateCollector ()
@@ -57,7 +58,7 @@ private static IEnumerable<TestCase> AllCases ()
5758
return AllCases ().FirstOrDefault (c => c.Name == name);
5859
}
5960

60-
private static IEnumerable<object[]> TestNamesBySuiteName (string suiteName)
61+
private static IEnumerable<object[]> TestNamesBySuiteName ([CallerMemberName] string suiteName = "")
6162
{
6263
return AllCases ()
6364
.Where (c => c.TestSuiteDirectory.FileName == suiteName)

src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerDriver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace Mono.Linker.Tests.TestCasesRunner
1616
{
1717
public class ILCompilerDriver
1818
{
19-
private const string DefaultSystemModule = "System.Private.CoreLib";
19+
internal const string DefaultSystemModule = "System.Private.CoreLib";
2020

2121
public ILScanResults Trim (ILCompilerOptions options, ILogWriter logWriter)
2222
{

0 commit comments

Comments
 (0)