diff --git a/src/linker/Linker.Steps/MarkStep.cs b/src/linker/Linker.Steps/MarkStep.cs index e25dba452772..e772c52f69bf 100644 --- a/src/linker/Linker.Steps/MarkStep.cs +++ b/src/linker/Linker.Steps/MarkStep.cs @@ -3919,6 +3919,58 @@ void MarkFieldsFromReflectionCall (ref ReflectionPatternContext reflectionContex if (!foundMatch) reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve field `{name}` on type `{declaringType.FullName}`."); } + + void MarkPropertiesFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, bool staticOnly = false) + { + bool foundMatch = false; + foreach (var property in declaringType.Properties) { + if (property.Name != name) + continue; + + bool markedAny = false; + + // It is not easy to reliably detect in the IL code whether the getter or setter (or both) are used. + // Be conservative and mark everything for the property. + var getter = property.GetMethod; + if (getter != null && (!staticOnly || staticOnly && getter.IsStatic)) { + reflectionContext.RecordRecognizedPattern (getter, () => _markStep.MarkIndirectlyCalledMethod (getter)); + markedAny = true; + } + + var setter = property.SetMethod; + if (setter != null && (!staticOnly || staticOnly && setter.IsStatic)) { + reflectionContext.RecordRecognizedPattern (setter, () => _markStep.MarkIndirectlyCalledMethod (setter)); + markedAny = true; + } + + if (markedAny) { + foundMatch = true; + reflectionContext.RecordRecognizedPattern (property, () => _markStep.MarkProperty (property)); + } + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve property `{name}` on type `{declaringType.FullName}`."); + } + + void MarkFieldsFromReflectionCall (ref ReflectionPatternContext reflectionContext, TypeDefinition declaringType, string name, bool staticOnly = false) + { + bool foundMatch = false; + foreach (var field in declaringType.Fields) { + if (field.Name != name) + continue; + + if (staticOnly && !field.IsStatic) + continue; + + foundMatch = true; + reflectionContext.RecordRecognizedPattern (field, () => _markStep.MarkField (field)); + break; + } + + if (!foundMatch) + reflectionContext.RecordUnrecognizedPattern ($"Reflection call '{reflectionContext.MethodCalled.FullName}' inside '{reflectionContext.MethodCalling.FullName}' could not resolve field `{name}` on type `{declaringType.FullName}`."); + } } }