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
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<Description>Contracts for extending Microsoft.TemplateEngine.Core</Description>
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<Description>Common operations for instantiating templates using forward-only input stream operations</Description>
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public async Task SetInstalledTemplatePackagesAsync(IReadOnlyList<TemplatePackag
{
// Ignore FSW notifications received during writing changes (we'll notify synchronously)
_watcher?.Dispose();
_environmentSettings.Host.FileSystem.WriteObject(_globalSettingsFile, globalSettingsData);
_environmentSettings.Host.FileSystem.WriteObject(_globalSettingsFile, globalSettingsData, GlobalSettingsJsonSerializerContext.Default.GlobalSettingsData);
// We are ready for new notifications now
_watcher = CreateWatcherIfRequested();
SettingsChanged?.Invoke();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Json.Serialization;

namespace Microsoft.TemplateEngine.Edge.BuiltInManagedProvider
{
[JsonSourceGenerationOptions(DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(GlobalSettingsData))]
internal partial class GlobalSettingsJsonSerializerContext : JsonSerializerContext;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Concurrent;
using System.Reflection;
#if NET
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Loader;
#endif

Expand Down Expand Up @@ -43,6 +44,7 @@ internal static void Reset()
}

#if NET
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Assembly probing loads assemblies by path at runtime.")]
private static Assembly? SelectBestMatch(AssemblyLoadContext loadContext, AssemblyName match, IEnumerable<FileInfo> candidates)
#else
private static Assembly? SelectBestMatch(object sender, AssemblyName match, IEnumerable<FileInfo> candidates)
Expand Down Expand Up @@ -195,6 +197,7 @@ internal static void Reset()
}

#if NET
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Assembly resolution probes and loads assemblies at runtime.")]
private static Assembly? Resolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
#else
private static Assembly? Resolving(object sender, ResolveEventArgs resolveEventArgs)
Expand Down
25 changes: 24 additions & 1 deletion src/Microsoft.TemplateEngine.Edge/Settings/ComponentManager.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.

#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Reflection;
using Microsoft.TemplateEngine.Abstractions;
#if NET
Expand All @@ -18,6 +21,9 @@ internal class ComponentManager : IComponentManager
private readonly SettingsFilePaths _paths;
private readonly IEngineEnvironmentSettings _engineEnvironmentSettings;

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2057", Justification = "Component types are resolved by assembly-qualified name from the settings store.")]
#endif
public ComponentManager(IEngineEnvironmentSettings engineEnvironmentSettings)
{
_engineEnvironmentSettings = engineEnvironmentSettings;
Expand Down Expand Up @@ -119,6 +125,12 @@ public void RegisterMany(IEnumerable<Type> typeList)
}
}

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Components are resolved by name and instantiated via reflection.")]
[UnconditionalSuppressMessage("AOT", "IL2067", Justification = "Component type is resolved at runtime from stored assembly-qualified name.")]
[UnconditionalSuppressMessage("AOT", "IL2072", Justification = "Component type is resolved at runtime from stored assembly-qualified name.")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Component instantiation uses Activator.CreateInstance with runtime-resolved types.")]
#endif
public bool TryGetComponent<T>(Guid id, out T? component)
where T : class, IIdentifiedComponent
{
Expand Down Expand Up @@ -173,6 +185,13 @@ internal void AddProbingPath(string probeIn)
}

// This method does not save the settings, it just registers into the memory cache.
#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Component registration inspects and instantiates types via reflection.")]
[UnconditionalSuppressMessage("AOT", "IL2067", Justification = "Component type metadata is inspected at runtime.")]
[UnconditionalSuppressMessage("AOT", "IL2070", Justification = "Component type interfaces are enumerated at runtime.")]
[UnconditionalSuppressMessage("AOT", "IL3000", Justification = "Assembly.Location is used to register probing paths for component resolution.")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Component instantiation uses Activator.CreateInstance with runtime-resolved types.")]
#endif
private bool RegisterType(Type type)
{
if (!typeof(IIdentifiedComponent).IsAssignableFrom(type) || type.GetConstructor(Type.EmptyTypes) == null || !type.IsClass)
Expand Down Expand Up @@ -239,7 +258,7 @@ internal void Save()
{
try
{
_engineEnvironmentSettings.Host.FileSystem.WriteObject(_paths.SettingsFile, _settings);
_engineEnvironmentSettings.Host.FileSystem.WriteObject(_paths.SettingsFile, _settings, SettingsStoreJsonSerializerContext.Default.SettingsStore);
successfulWrite = true;
}
catch (IOException)
Expand Down Expand Up @@ -273,6 +292,10 @@ public void AddComponent(Type type, IIdentifiedComponent component)
ids.Add(component.Id);
}

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Assembly loading resolves assemblies by name at runtime.")]
[UnconditionalSuppressMessage("AOT", "IL2057", Justification = "Component type is resolved by stored assembly-qualified name.")]
#endif
private Type GetType(string typeName)
{
int commaIndex = typeName.IndexOf(',');
Expand Down
7 changes: 7 additions & 0 deletions src/Microsoft.TemplateEngine.Edge/Settings/Scanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Reflection;
#if NET
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Loader;
#endif
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -128,6 +129,9 @@ private MountPointScanSource GetOrCreateMountPointScanInfoForInstallSource(strin
throw new Exception(string.Format(LocalizableStrings.Scanner_Error_TemplatePackageLocationIsNotSupported, sourceLocation));
}

#if NET
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Component scanning uses Assembly.GetTypes() on dynamically loaded assemblies.")]
#endif
private void ScanForComponents(MountPointScanSource source)
{
_ = source ?? throw new ArgumentNullException(nameof(source));
Expand Down Expand Up @@ -258,6 +262,9 @@ private async Task<ScanResult> ScanMountPointForTemplatesAsync(
/// <param name="pattern">Filename pattern to use when searching for files.</param>
/// <param name="searchOption"><see cref="SearchOption"/> to use when searching for files.</param>
/// <returns>The list of loaded assemblies in format (filename, loaded assembly).</returns>
#if NET
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Assembly loading via AssemblyLoadContext.LoadFromStream() is inherently reflection-based.")]
#endif
private IEnumerable<KeyValuePair<string, Assembly>> LoadAllFromPath(
out IEnumerable<string> loadFailures,
string path,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Json.Serialization;

namespace Microsoft.TemplateEngine.Edge.Settings
{
[JsonSourceGenerationOptions(DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(SettingsStore))]
internal partial class SettingsStoreJsonSerializerContext : JsonSerializerContext;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Json.Serialization;

namespace Microsoft.TemplateEngine.Edge.Settings
{
[JsonSourceGenerationOptions(DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(TemplateCache))]
internal partial class TemplateCacheJsonSerializerContext : JsonSerializerContext;
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ await Task.WhenAll(Enumerable.Range(0, allTemplatePackages.Count).Select(async i

try
{
_environmentSettings.Host.FileSystem.WriteObject(_paths.TemplateCacheFile, cache);
_environmentSettings.Host.FileSystem.WriteObject(_paths.TemplateCacheFile, cache, TemplateCacheJsonSerializerContext.Default.TemplateCache);
}
catch (Exception ex)
{
Expand Down
6 changes: 6 additions & 0 deletions src/Microsoft.TemplateEngine.IDE/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection;
#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.Installer;
using Microsoft.TemplateEngine.Abstractions.TemplatePackage;
Expand Down Expand Up @@ -371,6 +374,9 @@ public void Register(Type type)
}

[Obsolete("Use ITemplateEngineHost.BuiltInComponents or AddComponent to add components.")]
#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Obsolete method; Assembly.GetTypes() is inherently reflection-based.")]
#endif
public void Register(Assembly assembly)
{
_engineEnvironmentSettings.Components.RegisterMany(assembly.GetTypes());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<Description>An extension for Template Engine that allows projects that still run to be used as templates</Description>
<IsPackable>true</IsPackable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@

using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Microsoft.TemplateEngine.Orchestrator.RunnableProjects.ValueForms
{
[JsonSerializable(typeof(string))]
internal partial class JsonEncodeSerializerContext : JsonSerializerContext;

internal class JsonEncodeValueFormFactory : ActionableValueFormFactory
{
internal const string FormIdentifier = "jsonEncode";

private static readonly JsonSerializerOptions JsonEncodeOptions = new()
private static readonly JsonEncodeSerializerContext JsonEncodeContext = new(new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
});

internal JsonEncodeValueFormFactory() : base(FormIdentifier) { }

protected override string Process(string value)
{
return JsonSerializer.Serialize(value, JsonEncodeOptions);
return JsonSerializer.Serialize(value, JsonEncodeContext.String);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
<IsPackable>true</IsPackable>
<EnablePublicApiAnalyzer>true</EnablePublicApiAnalyzer>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!--
Mark as Native AOT compatible. This will enable relevant analyzers.
https://learn.microsoft.com/dotnet/core/deploying/native-aot/#aot-compatibility-analyzers
-->
<IsAotCompatible Condition="$([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)')) == '.NETCoreApp'">true</IsAotCompatible>
</PropertyGroup>

<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
Expand Down
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.

#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Microsoft.TemplateEngine;
Expand Down Expand Up @@ -31,6 +34,10 @@ internal TemplateDiscoveryMetadata(string version, IReadOnlyList<ITemplateInfo>
[JsonInclude]
internal IReadOnlyDictionary<string, object> AdditionalData { get; }

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Serializes a known internal type (TemplateDiscoveryMetadata).")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Serializes a known internal type (TemplateDiscoveryMetadata).")]
#endif
internal JsonObject ToJObject()
{
return JExtensions.FromObject(this);
Expand Down
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.

#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -67,6 +70,10 @@ private class TemplatePackageSearchDataJsonConverter : System.Text.Json.Serializ
public override TemplatePackageSearchData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
=> throw new NotImplementedException();

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Templates and AdditionalData are serialized with known types.")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Templates and AdditionalData are serialized with known types.")]
#endif
public override void Write(Utf8JsonWriter writer, TemplatePackageSearchData value, JsonSerializerOptions options)
{
if (value == null)
Expand Down
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.

#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Text.Json.Nodes;
using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine;
Expand Down Expand Up @@ -96,6 +99,10 @@ internal static IDictionary<string, object> ReadAdditionalData(
return additionalData;
}

#if NET7_0_OR_GREATER
[UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Serializes a known internal type (TemplateSearchCache).")]
[UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Serializes a known internal type (TemplateSearchCache).")]
#endif
internal JsonObject ToJObject()
{
return JExtensions.FromObject(this);
Expand Down
Loading