Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explore WinForms feature switch coverage in System.Windows.Forms project #10866

Closed
wants to merge 6 commits into from
Closed
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
13 changes: 12 additions & 1 deletion src/System.Windows.Forms/src/System.Windows.Forms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,24 @@
IL Trim warnings which should be removed in order to make WinForms trimmable
See https://github.com/dotnet/winforms/issues/4649
-->
<NoWarn>$(NoWarn);IL2026;IL2050;IL2057;IL2062;IL2067;IL2070;IL2072;IL2075;IL2077;IL2080;IL2092;IL2093;IL2094;IL2096;IL2111</NoWarn>
<NoWarn>$(NoWarn);IL2050;IL2057;IL2062;IL2067;IL2070;IL2072;IL2075;IL2077;IL2080;IL2092;IL2093;IL2094;IL2096;IL2111</NoWarn>
<Win32Manifest>Resources\System\Windows\Forms\XPThemes.manifest</Win32Manifest>
<Deterministic>true</Deterministic>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<UsePublicApiAnalyzers>true</UsePublicApiAnalyzers>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>

<Target Name="UseLiveTrimAnalyzer"
BeforeTargets="CoreCompile">
<ItemGroup>
<Analyzer Remove="@(Analyzer)" Condition="'%(FileName)' == 'ILLink.RoslynAnalyzer'" />
<Analyzer Remove="@(Analyzer)" Condition="'%(FileName)' == 'ILLink.CodeFixProvider'" />
<Analyzer Include="c:\work\core\CurrentWork\runtime\artifacts\bin\ILLink.RoslynAnalyzer\Debug\netstandard2.0\ILLink.RoslynAnalyzer.dll" />
<Analyzer Include="c:\work\core\CurrentWork\runtime\artifacts\bin\ILLink.CodeFixProvider\Debug\netstandard2.0\ILLink.CodeFixProvider.dll" />
</ItemGroup>
</Target>

<ItemGroup>
<None Remove="Resources\System\Windows\Forms\XPThemes.manifest" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ internal class AssemblyNamesTypeResolutionService : ITypeResolutionService

internal AssemblyNamesTypeResolutionService(AssemblyName[]? names) => _names = names;

[RequiresUnreferencedCode("Calls System.Resources.AssemblyNamesTypeResolutionService.GetAssembly(AssemblyName, Boolean)")]
public Assembly? GetAssembly(AssemblyName name) => GetAssembly(name, true);

[UnconditionalSuppressMessage("SingleFile", "IL3002", Justification = "Handles single file case")]
[RequiresUnreferencedCode("Calls System.Reflection.Assembly.LoadFrom(String)")]
public Assembly? GetAssembly(AssemblyName name, bool throwOnError)
{
_cachedAssemblies ??= new();
Expand Down Expand Up @@ -69,8 +71,10 @@ public string GetPathOfAssembly(AssemblyName name)

public Type? GetType(string name) => GetType(name, true);

[RequiresUnreferencedCode("Calls System.Resources.AssemblyNamesTypeResolutionService.GetType(String, Boolean, Boolean)")]
public Type? GetType(string name, bool throwOnError) => GetType(name, throwOnError, false);

[RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String, Boolean, Boolean)")]
public Type? GetType(string name, bool throwOnError, bool ignoreCase)
{
// Check type cache first
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;
Expand Down Expand Up @@ -217,6 +217,7 @@ private static string ToBase64WrappedString(byte[] data)
return raw;
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetConverter(Type)")]
private void FillDataNodeInfoFromObject(DataNodeInfo nodeInfo, object? value)
{
if (value is CultureInfo cultureInfo)
Expand Down Expand Up @@ -287,6 +288,7 @@ private void FillDataNodeInfoFromObject(DataNodeInfo nodeInfo, object? value)
#pragma warning restore SYSLIB0051

#pragma warning disable SYSLIB0011 // Type or member is obsolete
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
static void SerializeWithBinaryFormatter(
IFormatter? binaryFormatter,
DataNodeInfo nodeInfo,
Expand Down Expand Up @@ -325,6 +327,7 @@ static void SerializeWithBinaryFormatter(
#pragma warning restore SYSLIB0011
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetConverter(Type)")]
private object? GenerateObjectFromDataNodeInfo(DataNodeInfo dataNodeInfo, ITypeResolutionService? typeResolver)
{
string? mimeTypeName = dataNodeInfo.MimeType;
Expand Down Expand Up @@ -398,6 +401,7 @@ Type ResolveTypeName(string typeName)
return type;
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetConverter(Type)")]
object? ResolveMimeType(string mimeTypeName)
{
if (string.Equals(mimeTypeName, ResXResourceWriter.ByteArraySerializedObjectMimeType)
Expand All @@ -414,6 +418,7 @@ Type ResolveTypeName(string typeName)
}

[Obsolete(DiagnosticId = "SYSLIB0051")]
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
private object? GenerateObjectFromBinaryDataNodeInfo(DataNodeInfo dataNodeInfo, ITypeResolutionService? typeResolver)
{
if (!string.Equals(dataNodeInfo.MimeType, ResXResourceWriter.BinSerializedObjectMimeType))
Expand Down Expand Up @@ -459,6 +464,7 @@ Type ResolveTypeName(string typeName)
return result;
}

[RequiresUnreferencedCode("Calls System.Resources.ResXDataNode.FillDataNodeInfoFromObject(DataNodeInfo, Object)")]
internal DataNodeInfo GetDataNodeInfo()
{
bool shouldSerialize = true;
Expand Down Expand Up @@ -512,6 +518,7 @@ internal DataNodeInfo GetDataNodeInfo()
/// <summary>
/// Retrieves the type name for the value by using the specified type resolution service
/// </summary>
[RequiresUnreferencedCode("")]
public string? GetValueTypeName(ITypeResolutionService? typeResolver)
{
// The type name here is always a fully qualified name.
Expand Down Expand Up @@ -595,6 +602,7 @@ internal DataNodeInfo GetDataNodeInfo()
/// <summary>
/// Retrieves the object that is stored by this node by using the specified type resolution service.
/// </summary>
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
public object? GetValue(ITypeResolutionService? typeResolver)
{
if (_value is not null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ internal void OnInPlaceDeactivate(AxHost site)
}
}

[RequiresUnreferencedCode("Calls System.Windows.Forms.AxHost.SetSelectionStyle(Int32)")]
internal void OnUIDeactivate(AxHost site)
{
Debug.Assert(_siteUIActive is null || _siteUIActive == site, "Deactivating when not active");
Expand Down Expand Up @@ -634,6 +635,7 @@ internal void OnExitEditMode(AxHost ctl)
_controlInEditMode = null;
}

[RequiresUnreferencedCode("Calls System.Windows.Forms.AxHost.SetSelectionStyle(Int32)")]
HRESULT IOleInPlaceFrame.Interface.SetActiveObject(IOleInPlaceActiveObject* pActiveObject, PCWSTR pszObjName)
{
if (_siteUIActive is { } activeHost)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public AxEnumConverter(AxPropertyDescriptor target, Com2Enum com2Enum)
_target = target;
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
public override StandardValuesCollection? GetStandardValues(ITypeDescriptorContext? context)
{
// Make sure the converter has been properly refreshed by calling the Converter property.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public override Type ComponentType
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
public override TypeConverter Converter
{
[RequiresUnreferencedCode(TrimmingConstants.PropertyDescriptorPropertyTypeMessage)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@ HRESULT IOleInPlaceSite.Interface.OnPosRectChange(RECT* lprcPosRect)

// IPropertyNotifySink methods

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
HRESULT IPropertyNotifySink.Interface.OnChanged(int dispid)
{
// Some controls fire OnChanged() notifications when getting values of some properties.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ internal class PropertyBagStream : IPropertyBag.Interface

internal PropertyBagStream() => _bag = new();

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
internal PropertyBagStream(Stream stream)
{
long position = stream.Position;
Expand Down Expand Up @@ -93,6 +94,7 @@ HRESULT IPropertyBag.Interface.Write(PCWSTR pszPropName, VARIANT* pVar)
return HRESULT.S_OK;
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
internal void Save(Stream stream)
{
long position = stream.Position;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Specialized;
Expand Down Expand Up @@ -980,6 +980,7 @@ protected override void OnLostFocus(EventArgs e)
}
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetProperties(Object)")]
private void OnNewSelection(object? sender, EventArgs e)
{
if (IsUserMode() || !Site.TryGetService(out ISelectionService? selectionService))
Expand Down Expand Up @@ -2398,6 +2399,7 @@ private void CreateInstance()
return null;
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetProperties(Object)")]
Copy link
Member

Choose a reason for hiding this comment

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

@LakshanF

This only comes into play when running in the designer (when you actually have a Site for the Component). I'm not sure how we would deal with this in a way that would give meaningful feedback. It isn't an expected runtime scenario.

I think this is one big bucket of things- anything that touches the Site.

Copy link
Member

Choose a reason for hiding this comment

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

I would actually expect annotating is the right answer here. Basically, we need to wall off the designer code from the app code, right?

So a mechanical way to do that is to annotate everything that uses the designer as RUC. If that code is successfully removed from all trimming code paths, the RUC warning won't fire because the code won't be called.

But this approach also helps catch bugs because it ensures that if a reference is ever added in the future, it will warn.

private void SetSelectionStyle(int selectionStyle)
{
if (IsUserMode())
Expand All @@ -2420,6 +2422,7 @@ private void SetSelectionStyle(int selectionStyle)
}

[EditorBrowsable(EditorBrowsableState.Advanced)]
[RequiresUnreferencedCode("")]
public void InvokeEditMode()
{
Debug.Assert((_flags & AxFlags.PreventEditMode) == 0, "edit mode should have been disabled");
Expand All @@ -2446,6 +2449,7 @@ public void InvokeEditMode()
//

[EditorBrowsable(EditorBrowsableState.Advanced)]
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "ICustomTypeDescriptor")]
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
if (!_axState[s_editorRefresh] && HasPropertyPages())
Expand Down Expand Up @@ -2527,6 +2531,7 @@ AttributeCollection ICustomTypeDescriptor.GetAttributes()
}

[EditorBrowsable(EditorBrowsableState.Advanced)]
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "ICustomTypeDescriptor")]
EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
=> TypeDescriptor.GetEvents(this, noCustomTypeDesc: true);

Expand Down Expand Up @@ -2565,6 +2570,7 @@ private bool RefreshAllProperties
}
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetProperties(Object, Attribute[], Boolean)")]
private PropertyDescriptorCollection FillProperties(Attribute[]? attributes)
{
if (RefreshAllProperties)
Expand Down Expand Up @@ -2735,6 +2741,7 @@ PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[]? at
return this;
}

[RequiresUnreferencedCode("Calls System.Windows.Forms.AxHost.FillProperties(Attribute[])")]
private AxPropertyDescriptor? GetPropertyDescriptorFromDispid(int dispid)
{
Debug.Assert(dispid != PInvokeCore.DISPID_UNKNOWN, "Wrong dispid sent to GetPropertyDescriptorFromDispid");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,7 @@ internal HRESULT InPlaceDeactivate()
/// <summary>
/// Looks at the property to see if it should be loaded / saved as a resource or through a type converter.
/// </summary>
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
private bool IsResourceProperty(PropertyDescriptor property)
{
TypeConverter converter = property.Converter;
Expand Down Expand Up @@ -1022,6 +1023,7 @@ internal HRESULT Load(IStorage* stg)
}

/// <inheritdoc cref="IPersistStreamInit.Load(IStream*)"/>
[RequiresUnreferencedCode("Calls System.Windows.Forms.Control.ActiveXImpl.Load(IPropertyBag*, IErrorLog*)")]
internal void Load(IStream* stream)
{
// We do everything through property bags because we support full fidelity
Expand All @@ -1033,6 +1035,7 @@ internal void Load(IStream* stream)
}

/// <inheritdoc cref="IPersistPropertyBag.Load(IPropertyBag*, IErrorLog*)"/>
[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetProperties(Object, Attribute[])")]
internal unsafe void Load(IPropertyBag* propertyBag, IErrorLog* errorLog)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(
Expand Down Expand Up @@ -1105,6 +1108,7 @@ internal unsafe void Load(IPropertyBag* propertyBag, IErrorLog* errorLog)
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
bool SetValue(PropertyDescriptor currentProperty, object data)
{
string? value = data as string ?? Convert.ToString(data, CultureInfo.InvariantCulture);
Expand Down Expand Up @@ -1336,6 +1340,7 @@ internal void OnFocus(bool focus)
};

/// <inheritdoc cref="IQuickActivate.QuickActivate(QACONTAINER*, QACONTROL*)"/>
[RequiresUnreferencedCode("Calls GetDefaultEventsInterface(Type)")]
internal unsafe HRESULT QuickActivate(QACONTAINER* pQaContainer, QACONTROL* pQaControl)
{
if (pQaControl is null)
Expand Down Expand Up @@ -1416,6 +1421,7 @@ internal unsafe HRESULT QuickActivate(QACONTAINER* pQaContainer, QACONTROL* pQaC
return HRESULT.S_OK;

// Get the default COM events interface declared on a .NET class.
[RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String, Boolean)")]
static Type? GetDefaultEventsInterface(Type controlType)
{
Type? eventInterface = null;
Expand Down Expand Up @@ -1467,6 +1473,7 @@ internal void Save(IStream* stream, BOOL fClearDirty)
}

/// <inheritdoc cref="IPersistPropertyBag.Save(IPropertyBag*, BOOL, BOOL)"/>
[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
internal void Save(IPropertyBag* propertyBag, BOOL clearDirty, BOOL saveAllProperties)
{
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ HRESULT IPersistPropertyBag.Interface.GetClassID(Guid* pClassID)
}

/// <inheritdoc cref="IPersistPropertyBag.Load(IPropertyBag*, IErrorLog*)"/>
[RequiresUnreferencedCode("Calls System.Windows.Forms.Control.ActiveXImpl.Load(IPropertyBag*, IErrorLog*)")]
HRESULT IPersistPropertyBag.Interface.Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog)
{
ActiveXInstance.Load(pPropBag, pErrorLog);
Expand Down Expand Up @@ -452,6 +453,7 @@ HRESULT IPersistStreamInit.Interface.GetClassID(Guid* pClassID)
HRESULT IPersistStreamInit.Interface.IsDirty() => ActiveXInstance.IsDirty();

/// <inheritdoc cref="IPersistStreamInit.Load(IStream*)"/>
[RequiresUnreferencedCode("Calls System.Windows.Forms.Control.ActiveXImpl.Load(IStream*)")]
HRESULT IPersistStreamInit.Interface.Load(IStream* pStm)
{
if (pStm is null)
Expand Down Expand Up @@ -482,6 +484,7 @@ HRESULT IPersistStreamInit.Interface.Save(IStream* pStm, BOOL fClearDirty)
HRESULT IPersistStreamInit.Interface.InitNew() => HRESULT.S_OK;

/// <inheritdoc cref="IQuickActivate.QuickActivate(QACONTAINER*, QACONTROL*)"/>
[RequiresUnreferencedCode("Calls System.Windows.Forms.Control.ActiveXImpl.QuickActivate(QACONTAINER*, QACONTROL*)")]
HRESULT IQuickActivate.Interface.QuickActivate(QACONTAINER* pQaContainer, QACONTROL* pQaControl) =>
ActiveXInstance.QuickActivate(pQaContainer, pQaControl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public Com2ExtendedTypeConverter(TypeConverter? innerConverter)
_innerConverter = innerConverter;
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
public Com2ExtendedTypeConverter([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type baseType)
{
_innerConverter = TypeDescriptor.GetConverter(baseType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public Com2ExtendedUITypeEditor(UITypeEditor? baseTypeEditor)
_innerEditor = baseTypeEditor;
}

[RequiresUnreferencedCode("Calls System.ComponentModel.TypeDescriptor.GetEditor(Type, Type)")]
public Com2ExtendedUITypeEditor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type baseType)
{
_innerEditor = (UITypeEditor?)TypeDescriptor.GetEditor(baseType, typeof(UITypeEditor));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public override void RegisterEvents(Com2PropertyDescriptor[]? properties)
/// Here is where we handle IVsPerPropertyBrowsing.GetLocalizedPropertyInfo and IVsPerPropertyBrowsing.
/// Hide properties such as IPerPropertyBrowsing, IProvidePropertyBuilder, etc.
/// </summary>
[RequiresUnreferencedCode("Calls System.Windows.Forms.ComponentModel.Com2Interop.Com2IManagedPerPropertyBrowsingHandler.GetComponentAttributes(IVSMDPerPropertyBrowsing*, Int32)")]
Copy link
Member

Choose a reason for hiding this comment

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

This class is highly unlikely to come up. It is a VS specific support interface.

private void OnGetAttributes(Com2PropertyDescriptor sender, GetAttributesEvent e)
{
using var propertyBrowsing = TryGetComScope(sender.TargetObject, out HRESULT hr);
Expand All @@ -43,6 +44,7 @@ private void OnGetAttributes(Com2PropertyDescriptor sender, GetAttributesEvent e
}
}

[RequiresUnreferencedCode("Calls System.Reflection.Assembly.GetType(String)")]
internal static Attribute[] GetComponentAttributes(IVSMDPerPropertyBrowsing* propertyBrowsing, int dispid)
{
uint attributeCount = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ private void OnGetBaseAttributes(Com2PropertyDescriptor sender, GetAttributesEve
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
private void OnGetDisplayValue(Com2PropertyDescriptor sender, GetNameItemEvent e)
{
using var propertyBrowsing = TryGetComScope(sender.TargetObject, out HRESULT hr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ public object Clone()

protected sealed override AttributeCollection CreateAttributeCollection() => new(AttributeArray);

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
private TypeConverter GetBaseTypeConverter()
{
if (PropertyType is null)
Expand Down Expand Up @@ -509,6 +510,7 @@ private TypeConverter GetBaseTypeConverter()
return localConverter ?? new TypeConverter();
}

[UnconditionalSuppressMessage("Trimming", "IL2026:", Justification = "<Pending>")]
private object? GetBaseTypeEditor(Type editorBaseType)
{
if (PropertyType is null)
Expand Down Expand Up @@ -673,6 +675,7 @@ internal unsafe VARIANT GetNativeValue(object? component)
/// the parameter will be passed in.
/// </para>
/// </remarks>
[RequiresUnreferencedCode("Calls System.Windows.Forms.ComponentModel.Com2Interop.ComNativeDescriptor.ResolveVariantTypeConverterAndTypeEditor(Object, ref TypeConverter, Type, ref Object)")]
public void GetTypeConverterAndTypeEditor([NotNull] ref TypeConverter? typeConverter, Type editorBaseType, ref object? typeEditor)
{
// Get the base editor and converter, attributes first.
Expand Down
Loading