Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ void MarkDynamicDependency (DynamicDependency dynamicDependency, MemberReference

IEnumerable<IMemberDefinition> members;
if (dynamicDependency.MemberSignature is string memberSignature) {
members = DocumentationSignatureParser.GetMembersByDocumentationSignature (type, memberSignature);
members = DocumentationSignatureParser.GetMembersByDocumentationSignature (type, memberSignature, acceptName: true);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is a light version of wildcard support, right? It will mark any members if ( is not part of the signature.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. I will note this in the docs.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

if (!members.Any ()) {
_context.LogWarning ($"No members were resolved for '{memberSignature}' in DynamicDependencyAttribute on '{context}'", 2037, MessageOrigin.TryGetOrigin (context.Resolve ()));
return;
Expand Down
57 changes: 30 additions & 27 deletions src/linker/Linker/DocumentationSignatureParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ public static IEnumerable<IMemberDefinition> GetMembersForDocumentationSignature
}

// Takes a member signature (not including the declaring type) and returns the matching members on the type.
public static IEnumerable<IMemberDefinition> GetMembersByDocumentationSignature (TypeDefinition type, string signature)
public static IEnumerable<IMemberDefinition> GetMembersByDocumentationSignature (TypeDefinition type, string signature, bool acceptName = false)
{
int index = 0;
var results = new List<IMemberDefinition> ();
var nameBuilder = new StringBuilder ();
var (name, arity) = DocumentationSignatureParser.ParseTypeOrNamespaceName (signature, ref index, nameBuilder);
DocumentationSignatureParser.GetMatchingMembers (signature, ref index, type.Module, type, name, arity, DocumentationSignatureParser.MemberType.All, results);
DocumentationSignatureParser.GetMatchingMembers (signature, ref index, type.Module, type, name, arity, DocumentationSignatureParser.MemberType.All, results, acceptName);
return results;
}

Expand Down Expand Up @@ -195,7 +195,7 @@ public static void ParseSignaturePart (string id, ref int index, ModuleDefinitio
// Gets all members of the specified member kinds of the containing type, with
// mathing name, arity, and signature at the current index (for methods and properties).
// This will also resolve types from the given module if no containing type is given.
public static void GetMatchingMembers (string id, ref int index, ModuleDefinition module, TypeDefinition? containingType, string memberName, int arity, MemberType memberTypes, List<IMemberDefinition> results)
public static void GetMatchingMembers (string id, ref int index, ModuleDefinition module, TypeDefinition? containingType, string memberName, int arity, MemberType memberTypes, List<IMemberDefinition> results, bool acceptName = false)
{
if (memberTypes.HasFlag (MemberType.Type))
GetMatchingTypes (module, containingType, memberName, arity, results);
Expand All @@ -207,13 +207,13 @@ public static void GetMatchingMembers (string id, ref int index, ModuleDefinitio
int endIndex = index;

if (memberTypes.HasFlag (MemberType.Method)) {
GetMatchingMethods (id, ref index, containingType, memberName, arity, results);
GetMatchingMethods (id, ref index, containingType, memberName, arity, results, acceptName);
endIndex = index;
index = startIndex;
}

if (memberTypes.HasFlag (MemberType.Property)) {
GetMatchingProperties (id, ref index, containingType, memberName, results);
GetMatchingProperties (id, ref index, containingType, memberName, results, acceptName);
endIndex = index;
index = startIndex;
}
Expand Down Expand Up @@ -527,7 +527,7 @@ static void GetMatchingTypes (ModuleDefinition module, TypeDefinition? declaring
}
}

static void GetMatchingMethods (string id, ref int index, TypeDefinition? type, string memberName, int arity, List<IMemberDefinition> results)
static void GetMatchingMethods (string id, ref int index, TypeDefinition? type, string memberName, int arity, List<IMemberDefinition> results, bool acceptName = false)
{
if (type == null)
return;
Expand All @@ -546,38 +546,41 @@ static void GetMatchingMethods (string id, ref int index, TypeDefinition? type,
continue;

parameters.Clear ();
bool isNameOnly = true;
if (PeekNextChar (id, index) == '(') {
isNameOnly = false;
// if the parameters cannot be identified (some error), then the symbol cannot match, try next method symbol
if (!ParseParameterList (id, ref index, method, parameters))
continue;
}

// note: this allows extra characters at the end

if (!AllParametersMatch (method.Parameters, parameters))
continue;

if (PeekNextChar (id, index) == '~') {
isNameOnly = false;
index++;
string? returnType = ParseTypeSymbol (id, ref index, method);
if (returnType == null)
continue;

// if return type is specified, then it must match
if (GetSignaturePart (method.ReturnType) == returnType) {
results.Add (method);
endIndex = index;
}
} else {
// no return type specified, then any matches
results.Add (method);
endIndex = index;
if (GetSignaturePart (method.ReturnType) != returnType)
continue;
}

if (!isNameOnly || !acceptName) {
// check parameters unless we are matching a name only
if (!AllParametersMatch (method.Parameters, parameters))
continue;
}

results.Add (method);
endIndex = index;
}
index = endIndex;
}

static void GetMatchingProperties (string id, ref int index, TypeDefinition? type, string memberName, List<IMemberDefinition> results)
static void GetMatchingProperties (string id, ref int index, TypeDefinition? type, string memberName, List<IMemberDefinition> results, bool acceptName = false)
{
if (type == null)
return;
Expand All @@ -598,16 +601,16 @@ static void GetMatchingProperties (string id, ref int index, TypeDefinition? typ
} else {
parameters.Clear ();
}

if (ParseParameterList (id, ref index, property.DeclaringType, parameters)
&& AllParametersMatch (property.Parameters, parameters)) {
results.Add (property);
endIndex = index;
}
} else if (property.Parameters.Count == 0) {
results.Add (property);
endIndex = index;
if (!ParseParameterList (id, ref index, property.DeclaringType, parameters))
continue;
if (!AllParametersMatch (property.Parameters, parameters))
continue;
} else {
if (!acceptName && property.Parameters.Count != 0)
continue;
}
results.Add (property);
endIndex = index;
}

index = endIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ void Method2 (out sbyte arg)
[Kept]
[DynamicDependency ("Dependency1()", typeof (C))]
[DynamicDependency ("Dependency2``1(``0[],System.Int32", typeof (C))]
[DynamicDependency ("Dependency3", typeof (C))]
[DynamicDependency ("RecursiveDependency", typeof (C))]
[DynamicDependency ("#ctor()", typeof (C))] // To avoid lazy body marking stubbing
[DynamicDependency ("field", typeof (C))]
[DynamicDependency ("NextOne(Mono.Linker.Tests.Cases.DynamicDependencies.DynamicDependencyMethod.Nested@)", typeof (Nested))]
[DynamicDependency ("#cctor()", typeof (Nested))]
// Dependency on a property itself should be expressed as a dependency on one or both accessor methods
[DynamicDependency ("get_Property()", typeof (C))]
[DynamicDependency ("get_Property2", typeof (C))]
[DynamicDependency ("M``1(Mono.Linker.Tests.Cases.DynamicDependencies.DynamicDependencyMethod.Complex.S{" +
"Mono.Linker.Tests.Cases.DynamicDependencies.DynamicDependencyMethod.Complex.G{" +
"Mono.Linker.Tests.Cases.DynamicDependencies.DynamicDependencyMethod.Complex.A,``0}}" +
Expand Down Expand Up @@ -134,10 +137,30 @@ internal void Dependency2<T> (T[] arg1, int arg2)
{
}

[Kept]
internal void Dependency3 (string str)
{
}

[Kept]
[DynamicDependency ("#ctor", typeof (NestedInC))]
internal void RecursiveDependency ()
{
}

[KeptMember (".ctor()")]
class NestedInC
{
}

[Kept]
[KeptBackingField]
internal string Property { [Kept] get; set; }

[Kept]
[KeptBackingField]
internal string Property2 { [Kept] get; set; }

// For now, Condition has no effect: https://github.com/mono/linker/issues/1231
[Kept]
internal void ConditionalTest ()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,10 @@ public int this[int i] {
[ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.op_Addition(Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A)")]
[ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.op_Addition(Mono.Linker.Tests.DocumentationSignatureParserTests.A,Mono.Linker.Tests.DocumentationSignatureParserTests.A)")]
public static A operator + (A left, A right) => null;

[ExpectGeneratedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MWithReturnType")]
[ExpectExactlyResolvedDocumentationSignature ("M:Mono.Linker.Tests.DocumentationSignatureParserTests.A.MWithReturnType~System.Boolean")]
public static bool MWithReturnType () => false;
}

public struct S<T>
Expand Down