Skip to content
Open
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
25 changes: 22 additions & 3 deletions .github/workflows/net-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v3
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
3.1.x
8.0.x
8.0.x
10.0.x

- name: Restore dependencies
run: dotnet restore
Expand All @@ -30,3 +31,21 @@ jobs:

- name: Test
run: dotnet test --no-build --verbosity normal

aot-smoke:
runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Publish AOT smoke (win-x64)
run: dotnet publish tests/NetArchTest.AotSmoke -c Release -r win-x64

- name: Run AOT smoke exe
run: tests/NetArchTest.AotSmoke/bin/Release/net10.0/win-x64/publish/NetArchTest.AotSmoke.exe
155 changes: 155 additions & 0 deletions NetArchTest.eNhancedEdition.sln

Large diffs are not rendered by default.

46 changes: 34 additions & 12 deletions sources/NetArchTest/Assemblies/PublicUse/TypeContainer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System;
using System.Diagnostics;
#if NET10_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using Mono.Cecil;
using NetArchTest.Rules;

Expand All @@ -23,23 +26,42 @@ internal sealed class TypeContainer : IType
public string SourceFilePath => _sourceFilePath.Value;


#if NET10_0_OR_GREATER
[UnconditionalSuppressMessage("Trim analysis", "IL2026",
Justification = "Lazy<Type> body delegates to ResolveReflectionType (annotated). Tier 1 paths never read ReflectionType.")]
[UnconditionalSuppressMessage("AOT analysis", "IL3050",
Justification = "Lazy<Type> body delegates to ResolveReflectionType (annotated). Tier 1 paths never read ReflectionType.")]
#endif
internal TypeContainer(TypeDefinition monoTypeDefinition, string explanation)
{
_monoTypeDefinition = monoTypeDefinition;
_reflactionType = new Lazy<Type>(() =>
{
try
{
return _monoTypeDefinition.ToType();
}
catch
{
}
return null;
});
_reflactionType = new Lazy<Type>(() => ResolveReflectionType(_monoTypeDefinition));
_sourceFilePath = new Lazy<string>(() => _monoTypeDefinition.GetFilePath());
Explanation = explanation;
}
}


/// <summary>
/// Extracted Lazy initializer body so the trim analyzer can attribute the
/// reflection-into-Mono.Cecil call cleanly. Tier 1 paths never read
/// <see cref="ReflectionType"/>, so this method is unreachable for AOT consumers
/// who only use Tier 1.
/// </summary>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
private static Type ResolveReflectionType(TypeDefinition monoTypeDefinition)
{
try
{
return monoTypeDefinition.ToType();
}
catch
{
}
return null;
}


public static implicit operator Type(TypeContainer type)
Expand Down
35 changes: 35 additions & 0 deletions sources/NetArchTest/Condition_Dependencies.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using NetArchTest.Functions;
#if NET10_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace NetArchTest.Rules
{
Expand All @@ -9,6 +12,10 @@ public sealed partial class Condition
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList HaveDependencyOnAny(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.HaveDependencyOnAny(context, inputTypes, dependencies, true));
Expand All @@ -20,6 +27,10 @@ public ConditionList HaveDependencyOnAny(params string[] dependencies)
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList HaveDependencyOnAll(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.HaveDependencyOnAll(context, inputTypes, dependencies, true));
Expand All @@ -31,6 +42,10 @@ public ConditionList HaveDependencyOnAll(params string[] dependencies)
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList OnlyHaveDependencyOn(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.OnlyHaveDependenciesOnAnyOrNone(context, inputTypes, dependencies, true));
Expand All @@ -42,6 +57,10 @@ public ConditionList OnlyHaveDependencyOn(params string[] dependencies)
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList NotHaveDependencyOnAny(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.HaveDependencyOnAny(context, inputTypes, dependencies, false));
Expand All @@ -53,6 +72,10 @@ public ConditionList NotHaveDependencyOnAny(params string[] dependencies)
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList NotHaveDependencyOnAll(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.HaveDependencyOnAll(context, inputTypes, dependencies, false));
Expand All @@ -64,6 +87,10 @@ public ConditionList NotHaveDependencyOnAll(params string[] dependencies)
/// </summary>
/// <param name="dependencies">The dependencies to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList HaveDependencyOtherThan(params string[] dependencies)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.OnlyHaveDependenciesOnAnyOrNone(context, inputTypes, dependencies, false));
Expand All @@ -76,6 +103,10 @@ public ConditionList HaveDependencyOtherThan(params string[] dependencies)
/// </summary>
/// <param name="users">The types to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList BeUsedByAny(params string[] users)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.AreUsedByAny(context, inputTypes, users, true));
Expand All @@ -87,6 +118,10 @@ public ConditionList BeUsedByAny(params string[] users)
/// </summary>
/// <param name="users">The types to match against. These can be namespaces or specific types.</param>
/// <returns>An updated set of conditions that can be applied to a list of types.</returns>
#if NET10_0_OR_GREATER
[RequiresUnreferencedCode(NetArchTestAotMessages.DependencySearch)]
[RequiresDynamicCode(NetArchTestAotMessages.DependencySearch)]
#endif
public ConditionList NotBeUsedByAny(params string[] users)
{
AddFunctionCall((context, inputTypes) => FunctionDelegates.AreUsedByAny(context, inputTypes, users, false));
Expand Down
Loading