diff --git a/PolySharp.slnx b/PolySharp.slnx
index 3b5474c..f3e0503 100644
--- a/PolySharp.slnx
+++ b/PolySharp.slnx
@@ -9,6 +9,7 @@
+
diff --git a/src/PolySharp.SourceGenerators/Extensions/CompilationExtensions.cs b/src/PolySharp.SourceGenerators/Extensions/CompilationExtensions.cs
index 9d934e7..ce421cf 100644
--- a/src/PolySharp.SourceGenerators/Extensions/CompilationExtensions.cs
+++ b/src/PolySharp.SourceGenerators/Extensions/CompilationExtensions.cs
@@ -50,18 +50,51 @@ public static bool HasAccessibleTypeWithMetadataName(this Compilation compilatio
// If there is only a single matching symbol, check its accessibility
if (compilation.GetTypeByMetadataName(fullyQualifiedMetadataName) is INamedTypeSymbol typeSymbol)
{
- return compilation.IsSymbolAccessibleWithin(typeSymbol, compilation.Assembly);
+ return isSymbolAccessible(typeSymbol);
}
// Otherwise, check all available types
foreach (INamedTypeSymbol currentTypeSymbol in compilation.GetTypesByMetadataName(fullyQualifiedMetadataName))
{
- if (compilation.IsSymbolAccessibleWithin(currentTypeSymbol, compilation.Assembly))
+ if (isSymbolAccessible(currentTypeSymbol))
{
return true;
}
}
return false;
+
+ bool isSymbolAccessible(INamedTypeSymbol symbol)
+ {
+ if (!compilation.IsSymbolAccessibleWithin(symbol, compilation.Assembly))
+ {
+ return false;
+ }
+ else if (!SymbolEqualityComparer.Default.Equals(compilation.Assembly, symbol.ContainingAssembly))
+ {
+ foreach (AttributeData attribute in symbol.GetAttributes())
+ {
+ if (attribute.AttributeClass is
+ {
+ ContainingNamespace:
+ {
+ ContainingNamespace:
+ {
+ ContainingNamespace.IsGlobalNamespace: true,
+ Name: "Microsoft",
+ },
+ Name: "CodeAnalysis",
+
+ },
+ Name: "EmbeddedAttribute",
+ })
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
}
}
\ No newline at end of file
diff --git a/tests/PolySharp.InternalsVisibleTo.Tests/LanguageFeatures.cs b/tests/PolySharp.InternalsVisibleTo.Tests/LanguageFeatures.cs
new file mode 100644
index 0000000..012a4c9
--- /dev/null
+++ b/tests/PolySharp.InternalsVisibleTo.Tests/LanguageFeatures.cs
@@ -0,0 +1,299 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+#if !NETSTANDARD2_1
+using System.Threading.Tasks;
+#endif
+
+#pragma warning disable CA2255
+
+namespace PolySharp.InternalsVisibleTo.Tests;
+
+internal class TestClass
+{
+ private string? name;
+
+ // AllowNullAttribute
+ public void TakeValue1([AllowNull] string name)
+ {
+ }
+
+ // DisallowNullAttribute
+ public void TakeValue2([DisallowNull] string? name)
+ {
+ }
+
+ // DoesNotReturnAttribute
+ [DoesNotReturn]
+ public void Throws()
+ {
+ throw null!;
+ }
+
+ // DoesNotReturnIfAttribute
+ public void Throws([DoesNotReturnIf(true)] bool value)
+ {
+ }
+
+ // MaybeNullAttribute
+ [return: MaybeNull]
+ public string ModifyValue()
+ {
+ return null;
+ }
+
+ // MaybeNullWhenAttribute
+ public bool ModifyValue([MaybeNullWhen(true)] out string result)
+ {
+ result = null;
+
+ return true;
+ }
+
+ // MemberNotNullAttribute
+ [MemberNotNull(nameof(name))]
+ public void AssignsField()
+ {
+ this.name = "";
+ }
+
+ // MemberNotNullWhenAttribute
+ [MemberNotNullWhen(true, nameof(name))]
+ public bool ConditionallyAssignsField()
+ {
+ this.name = "";
+
+ return true;
+ }
+
+ // NotNullAttribute
+ public void TakeValue3([NotNull] string? value)
+ {
+ throw null!;
+ }
+
+ // NotNullIfNotNullAttribute
+ [return: NotNullIfNotNull(nameof(value))]
+ public string? TakeValue4(string? value)
+ {
+ return value;
+ }
+
+ // NotNullWhenAttribute
+ public bool TakeValue([NotNullWhen(true)] out string? value)
+ {
+ value = this.name ?? "";
+
+ return true;
+ }
+
+ [RequiresPreviewFeatures]
+ public void PreviewApi()
+ {
+ }
+
+ public void TakeRegex([StringSyntax(StringSyntaxAttribute.Regex)] string pattern)
+ {
+ }
+
+ [ModuleInitializer]
+ public static void InitializeModule()
+ {
+ }
+
+ public void RefReadonlyMethod(ref readonly int x)
+ {
+ }
+
+ [Experimental("PS0001")]
+ public void ExperimentalMethod()
+ {
+ }
+}
+
+internal class TestClassWithRequiredMembers
+{
+ // SetsRequiredMembersAttribute
+ [SetsRequiredMembers]
+#pragma warning disable IDE0290
+ public TestClassWithRequiredMembers()
+#pragma warning restore IDE0290
+ {
+ Name = "";
+ }
+
+ // CompilerFeatureRequiredAttribute, RequiredMemberAttribute
+ public required string Name { get; init; }
+}
+
+// IsExternalInit
+internal record Person(string Name);
+
+internal readonly struct TestStruct
+{
+ private readonly int number;
+
+ // UnscopedRefAttribute
+ [UnscopedRef]
+ public readonly ref readonly int GetRef()
+ {
+ return ref this.number;
+ }
+}
+
+internal static class IndexAndRangeTests
+{
+ // Index
+ public static int TestIndex(ReadOnlySpan numbers)
+ {
+ return numbers[^1];
+ }
+
+ // Range
+ public static ReadOnlySpan TestRange(ReadOnlySpan numbers)
+ {
+ return numbers[1..^4];
+ }
+}
+
+[CollectionBuilder(typeof(CollectionClass), nameof(Create))]
+internal class CollectionClass : IEnumerable
+{
+ public static CollectionClass Test()
+ {
+ Test2(1, 2, 3);
+
+ return [1, 2, 3];
+ }
+
+ public static void Test2(params CollectionClass collection)
+ {
+
+ }
+
+ public static CollectionClass Create(ReadOnlySpan values)
+ {
+ return new();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return null!;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return null!;
+ }
+}
+
+internal class AnotherTestClass
+{
+ // CallerArgumentExpressionAttribute
+ public string AutomaticName(int number, [CallerArgumentExpression(nameof(number))] string name = "")
+ {
+ return name;
+ }
+
+ [SkipLocalsInit]
+ public void Stackalloc()
+ {
+ _ = stackalloc int[8];
+ }
+
+ public void Handler(string name, [InterpolatedStringHandlerArgument(nameof(name))] ref TestHandler handler)
+ {
+ }
+}
+
+[InterpolatedStringHandler]
+internal struct TestHandler
+{
+}
+
+#if !NETSTANDARD2_1
+
+internal struct TaskLikeType
+{
+ [AsyncMethodBuilder(typeof(CustomAsyncMethodBuilder))]
+ public static async TaskLikeType TestAsync()
+ {
+ await Task.Delay(1);
+ }
+
+ private sealed class CustomAsyncMethodBuilder
+ {
+ public static CustomAsyncMethodBuilder Create()
+ {
+ return null!;
+ }
+
+ public TaskLikeType Task => default;
+
+ public void SetException(Exception e)
+ {
+ }
+
+ public void SetResult()
+ {
+ }
+
+ public void SetStateMachine(IAsyncStateMachine _)
+ {
+ }
+
+ public void AwaitOnCompleted(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ }
+
+ public void AwaitUnsafeOnCompleted(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ }
+
+ public void Start(ref TStateMachine stateMachine)
+ where TStateMachine : IAsyncStateMachine
+ {
+
+ }
+ }
+}
+
+#endif
+
+internal static class OverloadResolutionPriorityTests
+{
+ public static void Test()
+ {
+ TestOverload(1);
+ }
+
+ [Obsolete("Do not use", error: true)]
+ [OverloadResolutionPriority(-1)]
+ public static void TestOverload(int x)
+ {
+ }
+
+ public static void TestOverload(int x, int y = 0)
+ {
+ }
+}
+
+internal static class ConstantExpectedTests
+{
+ public static void CpuIntrinsic([ConstantExpected] int value)
+ {
+ }
+
+ public static void AnotherCpuIntrinsic([ConstantExpected(Min = 0, Max = 8)] int value)
+ {
+ }
+}
diff --git a/tests/PolySharp.InternalsVisibleTo.Tests/PolySharp.InternalsVisibleTo.Tests.csproj b/tests/PolySharp.InternalsVisibleTo.Tests/PolySharp.InternalsVisibleTo.Tests.csproj
new file mode 100644
index 0000000..8c37d27
--- /dev/null
+++ b/tests/PolySharp.InternalsVisibleTo.Tests/PolySharp.InternalsVisibleTo.Tests.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net472;net48;net481;netstandard2.0;netstandard2.1;net8.0;net9.0
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/PolySharp.InternalsVisibleTo.Tests/RuntimeSupport.cs b/tests/PolySharp.InternalsVisibleTo.Tests/RuntimeSupport.cs
new file mode 100644
index 0000000..6d6ca97
--- /dev/null
+++ b/tests/PolySharp.InternalsVisibleTo.Tests/RuntimeSupport.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+[assembly: TargetPlatform("windows6.1")]
+
+[assembly: DisableRuntimeMarshalling]
+
+namespace PolySharp.InternalsVisbleTo.Tests;
+
+internal class RandomApis
+{
+ [StackTraceHidden]
+ public void HideMe()
+ {
+ }
+}
+
+internal class PlatformSpecificApis
+{
+ [UnmanagedCallersOnly]
+ [SuppressGCTransition]
+ public static void NativeFunction()
+ {
+ }
+
+ [ObsoletedOSPlatform("windows6.1")]
+ public void Obsoleted()
+ {
+ }
+
+ [SupportedOSPlatform("windows6.1")]
+ public void Supported()
+ {
+ }
+
+ [SupportedOSPlatformGuard("windows6.1")]
+ public void SupportedGuard()
+ {
+ }
+
+ [UnsupportedOSPlatform("windows6.1")]
+ public void Unsupported()
+ {
+ }
+
+ [UnsupportedOSPlatformGuard("windows6.1")]
+ public void UnsupportedGuard()
+ {
+ }
+}
+
+internal class ReflectionApis
+{
+ [RequiresUnreferencedCode("No idea what I'll reflect on")]
+ public void ReflectOnSomethingCrazy()
+ {
+ }
+
+ public void ReflectOnInputType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type)
+ {
+ }
+
+ [DynamicDependency("PolySharp.Tests.ReflectionApis.ReflectOnSomethingCrazy()")]
+ public void ReflectDependingOnStuff()
+ {
+ }
+
+ [UnconditionalSuppressMessage("Don't worry about it", "0000")]
+ public void SuppressEverything(Type type)
+ {
+ _ = type.GetProperties();
+ }
+
+ [RequiresDynamicCode("This method creates some type at runtime")]
+ public void MakeUpSomeNewType()
+ {
+ }
+
+ [RequiresAssemblyFiles("This method needs access to the assembly files")]
+ public void ReferenceSomeAssemblyFile()
+ {
+ }
+}
+
+internal class AccessorApis
+{
+#pragma warning disable CS0169, IDE0044
+ private int field;
+#pragma warning restore CS0169, IDE0044
+
+ [StackTraceHidden]
+ public void HideMe()
+ {
+ }
+
+ [UnsafeAccessor(UnsafeAccessorKind.Field, Name = nameof(field))]
+ public static extern ref int GetField(RandomApis obj);
+}
+
+[InlineArray(16)]
+internal struct Int8
+{
+#pragma warning disable CS0169, IDE0044, IDE0051
+ private int value0;
+#pragma warning restore CS0169, IDE0044, IDE0051
+}
\ No newline at end of file
diff --git a/tests/PolySharp.Tests/LanguageFeatures.cs b/tests/PolySharp.Tests/LanguageFeatures.cs
index d5df709..a35bfaa 100644
--- a/tests/PolySharp.Tests/LanguageFeatures.cs
+++ b/tests/PolySharp.Tests/LanguageFeatures.cs
@@ -10,6 +10,8 @@
#pragma warning disable CA2255
+[assembly: InternalsVisibleTo("PolySharp.InternalsVisibleTo.Tests")]
+
namespace PolySharp.Tests;
internal class TestClass