Skip to content

Commit

Permalink
TypeDescriptor-related trimming supportType descriptor (#102094)
Browse files Browse the repository at this point in the history
  • Loading branch information
steveharter committed May 17, 2024
1 parent 1df4111 commit 0c64e66
Show file tree
Hide file tree
Showing 26 changed files with 1,978 additions and 156 deletions.
11 changes: 11 additions & 0 deletions src/coreclr/tools/aot/crossgen2/crossgen2_publish.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
<_IsPublishing>true</_IsPublishing>
</PropertyGroup>

<PropertyGroup>
<_ComObjectDescriptorSupport>false</_ComObjectDescriptorSupport>
</PropertyGroup>

<ItemGroup>
<RuntimeHostConfigurationOption Include="System.ComponentModel.TypeDescriptor.IsComObjectDescriptorSupported"
Condition="'$(_ComObjectDescriptorSupport)' != ''"
Value="$(_ComObjectDescriptorSupport)"
Trim="true" />
</ItemGroup>

<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />

<PropertyGroup>
Expand Down

Large diffs are not rendered by default.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
Expand Down Expand Up @@ -262,4 +321,10 @@
<data name="BinaryFormatterMessage" xml:space="preserve">
<value>BinaryFormatter serialization is obsolete and should not be used. See https://aka.ms/binaryformatter for more information.</value>
</data>
</root>
<data name="TypeIsNotRegistered" xml:space="preserve">
<value>The type {0} is not registered. Call 'TypeDescriptor.RegisterType()' to register the type.</value>
</data>
<data name="CustomTypeProviderNotImplemented" xml:space="preserve">
<value>Custom type providers must implement member {0}.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,14 @@
<Compile Include="System\ComponentModel\Design\IDictionaryService.cs" />
<Compile Include="System\ComponentModel\Design\IExtenderListService.cs" />
<Compile Include="System\ComponentModel\Design\ITypeDescriptorFilterService.cs" />
<Compile Include="$(CommonPath)System\Drawing\ColorConverterCommon.cs"
Link="System\Drawing\ColorConverterCommon.cs" />
<Compile Include="$(CommonPath)System\Drawing\ColorTable.cs"
Link="System\Drawing\ColorTable.cs" />
<Compile Include="$(CommonPath)System\Drawing\ColorConverterCommon.cs" Link="System\Drawing\ColorConverterCommon.cs" />
<Compile Include="$(CommonPath)System\Drawing\ColorTable.cs" Link="System\Drawing\ColorTable.cs" />
<Compile Include="System\Drawing\ColorConverter.cs" />
<Compile Include="System\Drawing\PointConverter.cs" />
<Compile Include="System\Drawing\RectangleConverter.cs" />
<Compile Include="System\Drawing\SizeConverter.cs" />
<Compile Include="System\Drawing\SizeFConverter.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs"
Link="Common\System\Obsoletions.cs" />
<Compile Include="$(CommonPath)System\Obsoletions.cs" Link="Common\System\Obsoletions.cs" />
<!-- New code introduced for netcoreapp 2.0 -->
<Compile Include="System\ComponentModel\AddingNewEventArgs.cs" />
<Compile Include="System\ComponentModel\AddingNewEventHandler.cs" />
Expand Down Expand Up @@ -184,6 +181,7 @@
<Compile Include="System\ComponentModel\ToolboxItemAttribute.cs" />
<Compile Include="System\ComponentModel\ToolboxItemFilterAttribute.cs" />
<Compile Include="System\ComponentModel\ToolboxItemFilterType.cs" />
<Compile Include="System\ComponentModel\TrimSafeReflectionHelper.cs" />
<Compile Include="System\ComponentModel\WarningException.cs" />
<Compile Include="System\ComponentModel\Design\ActiveDesignerEventArgs.cs" />
<Compile Include="System\ComponentModel\Design\ActiveDocumentEventHandler.cs" />
Expand Down Expand Up @@ -250,10 +248,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.RegularExpressions\gen\System.Text.RegularExpressions.Generator.csproj"
ReferenceOutputAssembly="false"
SetTargetFramework="TargetFramework=netstandard2.0"
OutputItemType="Analyzer" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Text.RegularExpressions\gen\System.Text.RegularExpressions.Generator.csproj" ReferenceOutputAssembly="false" SetTargetFramework="TargetFramework=netstandard2.0" OutputItemType="Analyzer" />
<Reference Include="System.Collections" />
<Reference Include="System.Collections.NonGeneric" />
<Reference Include="System.Collections.Specialized" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,31 @@ public ComponentResourceManager(Type t) : base(t)
/// </summary>
[RequiresUnreferencedCode("The Type of value cannot be statically discovered.")]
public virtual void ApplyResources(object value, string objectName, CultureInfo? culture)
{
ArgumentNullException.ThrowIfNull(value);
ArgumentNullException.ThrowIfNull(objectName);
ApplyResources(value, value.GetType(), objectName, culture);
}

/// <summary>
/// This method examines all the resources for the provided culture.
/// When it finds a resource with a key in the format of
/// &quot;[objectName].[property name]&quot; or &quot;[objectName]-[property name]&quot; it will apply that resource's value
/// to the corresponding property on the object. If there is no matching
/// property the resource will be ignored.
/// </summary>
public virtual void ApplyResourcesToRegisteredType(object value, string objectName, CultureInfo? culture)
{
ArgumentNullException.ThrowIfNull(value);
ArgumentNullException.ThrowIfNull(objectName);

Type typeFromValue = value.GetType();
TypeDescriptor.ValidateRegisteredType(typeFromValue);
ApplyResources(value, typeFromValue, objectName, culture);
}

private void ApplyResources(object value, Type typeFromValue, string objectName, CultureInfo? culture)
{
culture ??= CultureInfo.CurrentUICulture;

// The general case here will be to always use the same culture, so optimize for
Expand Down Expand Up @@ -148,7 +169,7 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo?

if (componentReflect)
{
PropertyDescriptor? prop = TypeDescriptor.GetProperties(value).Find(propName, IgnoreCase);
PropertyDescriptor? prop = TypeDescriptorGetProperties(value).Find(propName, IgnoreCase);

if (prop != null && !prop.IsReadOnly && (kvp.Value == null || prop.PropertyType.IsInstanceOfType(kvp.Value)))
{
Expand All @@ -161,16 +182,16 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo?

try
{
prop = value.GetType().GetProperty(propName, flags);
prop = prop = TrimSafeReflectionHelper.GetProperty(typeFromValue, propName, flags);
}
catch (AmbiguousMatchException)
{
// Looks like we ran into a conflict between a declared property and an inherited one.
// In such cases, we choose the most declared one.
Type? t = value.GetType();
Type? t = typeFromValue;
do
{
prop = t.GetProperty(propName, flags | BindingFlags.DeclaredOnly);
prop = TrimSafeReflectionHelper.GetProperty(t, propName, flags | BindingFlags.DeclaredOnly);
t = t.BaseType;
} while (prop == null && t != null && t != typeof(object));
}
Expand All @@ -181,6 +202,10 @@ public virtual void ApplyResources(object value, string objectName, CultureInfo?
}
}
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "Calling method either has RequiresUnreferencedCode or has registered types.")]
static PropertyDescriptorCollection TypeDescriptorGetProperties(object value) => TypeDescriptor.GetProperties(value);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,36 @@ public virtual AttributeCollection GetAttributes()
return new TypeConverter();
}

/// <summary>
/// The GetConverterFromRegisteredType method returns a type converter for the type this type
/// descriptor is representing.
/// </summary>
public virtual TypeConverter? GetConverterFromRegisteredType()
{
if (_parent != null)
{
return _parent.GetConverterFromRegisteredType();
}

if (RequireRegisteredTypes is null)
{
if (TypeDescriptor.RequireRegisteredTypes)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType));
}
}
else if (RequireRegisteredTypes == true)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetConverterFromRegisteredType));
}

return Forward();

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)]
TypeConverter? Forward() => GetConverter();
}

/// <summary>
/// The GetDefaultEvent method returns the event descriptor for the default
/// event on the object this type descriptor is representing.
Expand All @@ -103,10 +133,7 @@ public virtual AttributeCollection GetAttributes()

/// <summary>
/// The GetEvents method returns a collection of event descriptors
/// for the object this type descriptor is representing. An optional
/// attribute array may be provided to filter the collection that is
/// returned. If no parent is provided,this will return an empty
/// event collection.
/// for the object this type descriptor is representing.
/// </summary>
public virtual EventDescriptorCollection GetEvents()
{
Expand Down Expand Up @@ -136,12 +163,35 @@ public virtual EventDescriptorCollection GetEvents(Attribute[]? attributes)
return EventDescriptorCollection.Empty;
}

/// <summary>
/// Returns a collection of event descriptors
/// for the object this type descriptor is representing.
/// </summary>
public virtual EventDescriptorCollection GetEventsFromRegisteredType()
{
if (_parent != null)
{
return _parent.GetEventsFromRegisteredType();
}

if (RequireRegisteredTypes is null)
{
if (TypeDescriptor.RequireRegisteredTypes)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType));
}
}
else if (RequireRegisteredTypes == true)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetEventsFromRegisteredType));
}

return GetEvents();
}

/// <summary>
/// The GetProperties method returns a collection of property descriptors
/// for the object this type descriptor is representing. An optional
/// attribute array may be provided to filter the collection that is returned.
/// If no parent is provided,this will return an empty
/// property collection.
/// for the object this type descriptor is representing.
/// </summary>
[RequiresUnreferencedCode(PropertyDescriptor.PropertyDescriptorPropertyTypeMessage)]
public virtual PropertyDescriptorCollection GetProperties()
Expand All @@ -154,6 +204,36 @@ public virtual PropertyDescriptorCollection GetProperties()
return PropertyDescriptorCollection.Empty;
}

/// <summary>
/// The GetProperties method returns a collection of property descriptors
/// for the object this type descriptor is representing.
/// </summary>
public virtual PropertyDescriptorCollection GetPropertiesFromRegisteredType()
{
if (_parent != null)
{
return _parent.GetPropertiesFromRegisteredType();
}

if (RequireRegisteredTypes is null)
{
if (TypeDescriptor.RequireRegisteredTypes)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType));
}
}
else if (RequireRegisteredTypes == true)
{
TypeDescriptor.ThrowHelper.ThrowNotImplementedException_CustomTypeProviderMustImplememtMember(nameof(GetPropertiesFromRegisteredType));
}

return Forward();

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = TypeDescriptionProvider.ForwardFromRegisteredMessage)]
PropertyDescriptorCollection Forward() => GetProperties();
}

/// <summary>
/// The GetProperties method returns a collection of property descriptors
/// for the object this type descriptor is representing. An optional
Expand All @@ -180,5 +260,30 @@ public virtual PropertyDescriptorCollection GetProperties(Attribute[]? attribute
/// to use its default type description services.
/// </summary>
public virtual object? GetPropertyOwner(PropertyDescriptor? pd) => _parent?.GetPropertyOwner(pd);

/// <summary>
/// Whether types are required to be registered through <see cref="TypeDescriptionProvider.RegisterType{T}"/>.
/// </summary>
/// <remarks>
/// The default value is <see langword="null"/> which means that the type descriptor has not declared whether or not it is compatible registered types.
/// A type descriptor needs to implement this to return <see langword="true"/> or <see langword="false"/> if the feature switch
/// 'System.ComponentModel.TypeDescriptor.RequireRegisteredTypes' is enabled.
/// If <see langword="true"/> is returned, then the type descriptor must also implement
/// <see cref="ICustomTypeDescriptor.GetConverterFromRegisteredType()"/>,
/// <see cref="ICustomTypeDescriptor.GetEventsFromRegisteredType()"/>, and
/// <see cref="ICustomTypeDescriptor.GetPropertiesFromRegisteredType()"/>.
/// </remarks>
public virtual bool? RequireRegisteredTypes
{
get
{
if (_parent != null)
{
return _parent.RequireRegisteredTypes;
}

return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,13 @@ protected internal override IExtenderProvider[] GetExtenderProviders(object inst
}

public override bool IsSupportedType(Type type) => Provider.IsSupportedType(type);

public override bool IsRegisteredType(Type type) => Provider.IsRegisteredType(type);

public override bool? RequireRegisteredTypes => Provider.RequireRegisteredTypes;

public override ICustomTypeDescriptor? GetTypeDescriptorFromRegisteredType(Type objectType, object? instance) => Provider.GetTypeDescriptorFromRegisteredType(objectType, instance);

public override void RegisterType<[DynamicallyAccessedMembers(TypeDescriptor.RegisteredTypesDynamicallyAccessedMembers)] T>() => Provider.RegisterType<T>();
}
}

0 comments on commit 0c64e66

Please sign in to comment.