Skip to content

Enable trim analyzer #41683

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

Merged
merged 6 commits into from
Jun 3, 2022
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
6 changes: 0 additions & 6 deletions eng/Workarounds.props
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,4 @@
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>

<!-- Trim analyzers are automatically enabled by IsTrimming=true. They currently break when run on aspnetcore.
Remove when trimming analyzers are fixed: https://github.com/dotnet/aspnetcore/issues/41016 -->
<PropertyGroup>
<EnableTrimAnalyzer Condition=" '$(EnableTrimAnalyzer)' == ''">false</EnableTrimAnalyzer>
</PropertyGroup>

</Project>
2 changes: 2 additions & 0 deletions src/Components/Components/src/BindConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,7 @@ private static class FormatterDelegateCache
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect unknown underlying types are configured by application code to be retained.")]
private static BindFormatter<T> MakeTypeConverterFormatter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
Expand Down Expand Up @@ -2028,6 +2029,7 @@ bool ConvertToArray(object? obj, CultureInfo? culture, out T[]? value)
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect unknown underlying types are configured by application code to be retained.")]
private static BindParser<T> MakeTypeConverterConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
Expand Down
5 changes: 3 additions & 2 deletions src/Components/Components/src/CascadingParameterState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Reflection;
using Microsoft.AspNetCore.Components.Reflection;
using Microsoft.AspNetCore.Components.Rendering;
using static Microsoft.AspNetCore.Internal.LinkerFlags;

namespace Microsoft.AspNetCore.Components;

Expand Down Expand Up @@ -75,7 +76,7 @@ public static IReadOnlyList<CascadingParameterState> FindCascadingParameters(Com
}

private static ReflectedCascadingParameterInfo[] GetReflectedCascadingParameterInfos(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type componentType)
[DynamicallyAccessedMembers(Component)] Type componentType)
{
if (!_cachedInfos.TryGetValue(componentType, out var infos))
{
Expand All @@ -87,7 +88,7 @@ private static ReflectedCascadingParameterInfo[] GetReflectedCascadingParameterI
}

private static ReflectedCascadingParameterInfo[] CreateReflectedCascadingParameterInfos(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] Type componentType)
[DynamicallyAccessedMembers(Component)] Type componentType)
{
List<ReflectedCascadingParameterInfo>? result = null;
var candidateProps = ComponentProperties.GetCandidateBindableProperties(componentType);
Expand Down
1 change: 1 addition & 0 deletions src/Components/Components/src/DynamicComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public void Attach(RenderHandle renderHandle)
}

/// <inheritdoc />
[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "We expect that types used with DynamicComponent will be defined in assemblies that don't get trimmed.")]
public Task SetParametersAsync(ParameterView parameters)
{
// This manual parameter assignment logic will be marginally faster than calling
Expand Down
5 changes: 4 additions & 1 deletion src/Components/Components/src/LayoutAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using static Microsoft.AspNetCore.Internal.LinkerFlags;

namespace Microsoft.AspNetCore.Components;

/// <summary>
Expand All @@ -13,7 +16,7 @@ public sealed class LayoutAttribute : Attribute
/// Constructs an instance of <see cref="LayoutAttribute"/>.
/// </summary>
/// <param name="layoutType">The type of the layout.</param>
public LayoutAttribute(Type layoutType)
public LayoutAttribute([DynamicallyAccessedMembers(Component)] Type layoutType)
{
LayoutType = layoutType ?? throw new ArgumentNullException(nameof(layoutType));

Expand Down
1 change: 1 addition & 0 deletions src/Components/Components/src/LayoutView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public Task SetParametersAsync(ParameterView parameters)
return Task.CompletedTask;
}

[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Layout components are preserved because the LayoutAttribute constructor parameter is correctly annotated.")]
private void Render()
{
// In the middle goes the supplied content
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Components/src/RouteView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#nullable disable warnings

using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;
Expand Down Expand Up @@ -72,6 +73,7 @@ public Task SetParametersAsync(ParameterView parameters)
/// Renders the component.
/// </summary>
/// <param name="builder">The <see cref="RenderTreeBuilder"/>.</param>
[UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Layout components are preserved because the LayoutAttribute constructor parameter is correctly annotated.")]
protected virtual void Render(RenderTreeBuilder builder)
{
var pageLayoutType = RouteData.PageType.GetCustomAttribute<LayoutAttribute>()?.LayoutType
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Components/src/Routing/RouteTableFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Microsoft.AspNetCore.Components.Routing;

Expand Down Expand Up @@ -30,6 +31,7 @@ public static RouteTable Create(RouteKey routeKey)

public static void ClearCaches() => Cache.Clear();

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Application code does not get trimmed, and the framework does not define routable components.")]
private static List<Type> GetRouteableComponents(RouteKey routeKey)
{
var routeableComponents = new List<Type>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public DataAnnotationsEventSubscriptions(EditContext editContext, IServiceProvid
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Model types are expected to be defined in assemblies that do not get trimmed.")]
private void OnFieldChanged(object? sender, FieldChangedEventArgs eventArgs)
{
var fieldIdentifier = eventArgs.FieldIdentifier;
Expand All @@ -108,6 +109,7 @@ private void OnFieldChanged(object? sender, FieldChangedEventArgs eventArgs)
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Model types are expected to be defined in assemblies that do not get trimmed.")]
private void OnValidationRequested(object? sender, ValidationRequestedEventArgs e)
{
var validationContext = new ValidationContext(_editContext.Model, _serviceProvider, items: null);
Expand Down Expand Up @@ -152,6 +154,7 @@ public void Dispose()
}
}

[UnconditionalSuppressMessage("Trimming", "IL2080", Justification = "Model types are expected to be defined in assemblies that do not get trimmed.")]
private static bool TryGetValidatableProperty(in FieldIdentifier fieldIdentifier, [NotNullWhen(true)] out PropertyInfo? propertyInfo)
{
var cacheKey = (ModelType: fieldIdentifier.Model.GetType(), fieldIdentifier.FieldName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal sealed class ComponentParametersTypeCache
}
}

[RequiresUnreferencedCode("This type attempts to load component parameters that may be trimmed.")]
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to preserve component parameters.")]
private static Type? ResolveType(Key key, Assembly[] assemblies)
{
Assembly? assembly = null;
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Shared/src/RootComponentTypeCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace Microsoft.AspNetCore.Components;
Expand All @@ -24,6 +25,7 @@ internal sealed class RootComponentTypeCache
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Root components are expected to be defined in assemblies that do not get trimmed.")]
private static Type? ResolveType(Key key, Assembly[] assemblies)
{
Assembly? assembly = null;
Expand Down
2 changes: 2 additions & 0 deletions src/Components/Web/src/JSComponents/JSComponentInterop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ private static EventCallback CreateEventCallbackWithNoParameters(IJSObjectRefere
return new(null, callback);
}

[UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "EventCallback and EventCallback<TValue> constructors are referenced statically and will be preserved.")]
private static object CreateEventCallbackWithSingleParameter(Type eventCallbackType, IJSObjectReference? jsObjectReference)
{
var callback = jsObjectReference is null ? null : new Func<object, Task>(
Expand All @@ -195,6 +196,7 @@ internal readonly struct ParameterTypeCache
{
public readonly Dictionary<string, ParameterInfo> ParameterInfoByName;

[UnconditionalSuppressMessage("Trimming", "IL2067", Justification = "OpenComponent already has the right set of attributes")]
public ParameterTypeCache(Type componentType)
{
ParameterInfoByName = new(StringComparer.OrdinalIgnoreCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ internal WebAssemblyHostBuilder(IJSUnmarshalledRuntime jsRuntime, JsonSerializer
};
}

[UnconditionalSuppressMessage("Trimming", "IL2072", Justification = "Root components are expected to be defined in assemblies that do not get trimmed.")]
private void InitializeRegisteredRootComponents(IJSUnmarshalledRuntime jsRuntime)
{
var componentsCount = jsRuntime.InvokeUnmarshalled<int>(RegisteredComponentsInterop.GetRegisteredComponentsCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// Based on the implementation in https://raw.githubusercontent.com/dotnet/sdk/aad0424c0bfaa60c8bd136a92fd131e53d14561a/src/BuiltInTools/DotNetDeltaApplier/HotReloadAgent.cs

using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
Expand Down Expand Up @@ -153,6 +154,7 @@ internal static List<Assembly> TopologicalSort(Assembly[] assemblies)
Visit(assemblies, assembly, sortedAssemblies, visited);
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Hot reload is only expected to work when trimming is disabled.")]
static void Visit(Assembly[] assemblies, Assembly assembly, List<Assembly> sortedAssemblies, HashSet<string> visited)
{
var assemblyIdentifier = assembly.GetName().Name!;
Expand Down Expand Up @@ -214,6 +216,7 @@ public void ApplyDeltas(IReadOnlyList<UpdateDelta> deltas)
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Hot reload is only expected to work when trimming is disabled.")]
private static Type[] GetMetadataUpdateTypes(IReadOnlyList<UpdateDelta> deltas)
{
List<Type>? types = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public WebAssemblyComponentParameterDeserializer(

public static WebAssemblyComponentParameterDeserializer Instance { get; } = new WebAssemblyComponentParameterDeserializer(new ComponentParametersTypeCache());

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to preserve component parameter types.")]
public ParameterView DeserializeParameters(IList<ComponentParameter> parametersDefinitions, IList<object> parameterValues)
{
var parametersDictionary = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
Expand Down Expand Up @@ -80,7 +81,7 @@ public static ComponentParameter[] GetParameterDefinitions(string parametersDefi
return JsonSerializer.Deserialize<ComponentParameter[]>(parametersDefinitions, WebAssemblyComponentSerializationSettings.JsonSerializationOptions)!;
}

[RequiresUnreferencedCode("This API attempts to JSON deserialize types which might be trimmed.")]
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to preserve component parameter types.")]
public static IList<object> GetParameterValues(string parameterValues)
{
return JsonSerializer.Deserialize<IList<object>>(parameterValues, WebAssemblyComponentSerializationSettings.JsonSerializationOptions)!;
Expand Down
1 change: 1 addition & 0 deletions src/Hosting/Hosting/src/WebHostBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ private IServiceCollection BuildCommonServices(out AggregateException? hostingSt
}

[UnconditionalSuppressMessage("Trimmer", "IL2077", Justification = "Finding startup type in assembly requires unreferenced code. Surfaced to user in UseStartup(startupAssemblyName).")]
[UnconditionalSuppressMessage("Trimmer", "IL2072", Justification = "Finding startup type in assembly requires unreferenced code. Surfaced to user in UseStartup(startupAssemblyName).")]
private void ScanAssemblyAndRegisterStartup(ServiceCollection services, string startupAssemblyName)
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static class DotNetDispatcher
/// <param name="invocationInfo">The <see cref="DotNetInvocationInfo"/>.</param>
/// <param name="argsJson">A JSON representation of the parameters.</param>
/// <returns>A JSON representation of the return value, or null.</returns>
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to ensure return types of JSInvokable methods are retained.")]
public static string? Invoke(JSRuntime jsRuntime, in DotNetInvocationInfo invocationInfo, string argsJson)
{
// This method doesn't need [JSInvokable] because the platform is responsible for having
Expand Down Expand Up @@ -70,6 +71,7 @@ public static class DotNetDispatcher
/// <param name="invocationInfo">The <see cref="DotNetInvocationInfo"/>.</param>
/// <param name="argsJson">A JSON representation of the parameters.</param>
/// <returns>A JSON representation of the return value, or null.</returns>
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to ensure return types of JSInvokable methods are retained.")]
public static void BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, string argsJson)
{
// This method doesn't need [JSInvokable] because the platform is responsible for having
Expand Down Expand Up @@ -136,6 +138,7 @@ public static void BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo i
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to ensure return types of JSInvokable methods are retained.")]
private static void EndInvokeDotNetAfterTask(Task task, JSRuntime jsRuntime, in DotNetInvocationInfo invocationInfo)
{
if (task.Exception != null)
Expand Down Expand Up @@ -208,6 +211,7 @@ private static void EndInvokeDotNetAfterTask(Task task, JSRuntime jsRuntime, in
}
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to ensure return types of JSInvokable methods are retained.")]
internal static object?[] ParseArguments(JSRuntime jsRuntime, string methodIdentifier, string arguments, Type[] parameterTypes)
{
if (parameterTypes.Length == 0)
Expand Down Expand Up @@ -425,6 +429,7 @@ private static (MethodInfo methodInfo, Type[] parameterTypes) GetCachedMethodInf

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "We expect application code is configured to ensure JSInvokable methods are retained. https://github.com/dotnet/aspnetcore/issues/29946")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072", Justification = "We expect application code is configured to ensure JSInvokable methods are retained. https://github.com/dotnet/aspnetcore/issues/29946")]
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "We expect application code is configured to ensure JSInvokable methods are retained. https://github.com/dotnet/aspnetcore/issues/29946")]
private static Dictionary<string, (MethodInfo, Type[])> ScanAssemblyForCallableMethods(AssemblyKey assemblyKey)
{
// TODO: Consider looking first for assembly-level attributes (i.e., if there are any,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -20,6 +21,7 @@ public override bool CanConvert(Type typeToConvert)
return typeToConvert.IsGenericType && typeToConvert.GetGenericTypeDefinition() == typeof(DotNetObjectReference<>);
}

[UnconditionalSuppressMessage("Trimming", "IL2055", Justification = "We expect that types used with DotNetObjectReference are retained.")]
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions jsonSerializerOptions)
{
// System.Text.Json handles caching the converters per type on our behalf. No caching is required here.
Expand Down
2 changes: 2 additions & 0 deletions src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ protected JSRuntime()
return await InvokeAsync<TValue>(targetInstanceId, identifier, CancellationToken.None, args);
}

[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We expect application code is configured to ensure JS interop arguments are linker friendly.")]
internal ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(
long targetInstanceId,
string identifier,
Expand Down Expand Up @@ -225,6 +226,7 @@ protected internal virtual Task<Stream> ReadJSDataAsStreamAsync(IJSStreamReferen
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:RequiresUnreferencedCode", Justification = "We enforce trimmer attributes for JSON deserialized types on InvokeAsync.")]
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "We enforce trimmer attributes for JSON deserialized types on InvokeAsync.")]
internal bool EndInvokeJS(long taskId, bool succeeded, ref Utf8JsonReader jsonReader)
{
if (!_pendingTasks.TryRemove(taskId, out var tcs))
Expand Down
10 changes: 9 additions & 1 deletion src/Middleware/Spa/SpaProxy/src/SpaHostingStartup.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand All @@ -24,9 +25,16 @@ public void Configure(IWebHostBuilder builder)
.Build();

services.AddSingleton<SpaProxyLaunchManager>();
services.Configure<SpaDevelopmentServerOptions>(configuration.GetSection("SpaProxyServer"));
ConfigureOptions<SpaDevelopmentServerOptions>(services, configuration.GetSection("SpaProxyServer"));
services.TryAddEnumerable(ServiceDescriptor.Singleton<IStartupFilter, SpaProxyStartupFilter>());
}
});

[UnconditionalSuppressMessageAttribute("Trimming", "IL2026", Justification = "Configuration object's public properties are preserved.")]
static void ConfigureOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] T>(IServiceCollection services, IConfigurationSection section)
where T : class
{
services.Configure<T>(section);
}
}
}
Loading