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

Introduce new InternalsVisibleToAnalyzer analyzer (ACZ0112) with FriendAttribute concept #7086

Merged
merged 10 commits into from
Jan 23, 2024
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
3 changes: 2 additions & 1 deletion eng/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
<IsTestProject Condition="'$(IsTestHelperLibrary)' == 'true'">false</IsTestProject>
</PropertyGroup>

<PropertyGroup Condition="'$(SignAssembly)' != 'false'">
<!-- Exclude TestReferenceWithInternalsVisibleTo from strong name signing, as it is required for a test scenario -->
<PropertyGroup Condition="'$(SignAssembly)' != 'false' and !$(MSBuildProjectName.EndsWith('TestReferenceWithInternalsVisibleTo'))">
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)AzureSDKToolsKey.snk</AssemblyOriginatorKeyFile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using Verifier = Azure.ClientSdk.Analyzers.Tests.AzureAnalyzerVerifier<Azure.ClientSdk.Analyzers.InternalsVisibleToAnalyzer>;

namespace Azure.ClientSdk.Analyzers.Tests
{
public class AZC0112Tests
{
[Fact]
public async Task AZC0020WhenInheritingFromInternalInterface()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class {|AZC0112:MyClass|} : IInternalInterface
{
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenInheritingFromInternalInterfaceWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class MyClass : IInternalInterfaceWithFriendAttribute
{
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task AZC0020WhenDerivingFromInternalClass()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
internal class {|AZC0112:MyClass|} : InternalClass
{
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenInheritingFromInternalClassWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
internal class MyClass : InternalClassWithFriendAttribute
{
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task AZC0020WhenDeclaringInternalProperty()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class MyClass
{
internal InternalClass {|AZC0112:PropReferencesInternalType|} { {|AZC0112:get|}; set;}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenDeclaringInternalPropertyWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class MyClass
{
internal InternalClassWithFriendAttribute PropReferencesInternalType { get; set;}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenDeclaringInternalFieldWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class MyClass
{
internal InternalClassWithFriendAttribute fieldReferencesInternalType;
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task AZC0020WhenDeclaringInternalField()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;

namespace LibraryNamespace
{
public class MyClass
{
internal InternalClass {|AZC0112:fieldReferencesInternalType|};
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task AZC0020WhenReferencingInternalProperty()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;
using System.Reflection;

namespace LibraryNamespace
{
public class MyClass
{
public void MyMethod()
{
var myClass = new PublicClass();
var value = {|AZC0112:myClass.InternalProperty|};
}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenReferencingInternalPropertyWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;
using System.Reflection;

namespace LibraryNamespace
{
public class MyClass
{
public void MyMethod()
{
var myClass = new PublicClass();
var value = myClass.InternalPropertyWithFriendAttribute;
}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task AZC0020WhenReferencingInternalMethod()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;
using System.Reflection;

namespace LibraryNamespace
{
public class MyClass
{
public void MyMethod()
{
var myClass = new PublicClass();
{|AZC0112:myClass.InternalMethod|}();
}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

[Fact]
public async Task NoAZC0020WhenReferencingInternalMethodWithFriendAttribute()
{
string code = @"
using System;
using TestReferenceWithInternalsVisibleTo;
using System.Reflection;

namespace LibraryNamespace
{
public class MyClass
{
public void MyMethod()
{
var myClass = new PublicClass();
myClass.InternalMethodWithFriendAttribute();
}
}
}";
await Verifier.VerifyAnalyzerAsync(code, additionalReferences: new[] { typeof(TestReferenceWithInternalsVisibleTo.PublicClass) });
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<ProjectReference Include="..\Azure.ClientSdk.Analyzers\Azure.ClientSdk.Analyzers.csproj" />
<ProjectReference Include="..\TestReferenceWithInternalsVisibleTo\TestReferenceWithInternalsVisibleTo.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
Expand All @@ -18,14 +19,15 @@ namespace Azure.ClientSdk.Analyzers.Tests
{
private static readonly ReferenceAssemblies DefaultReferenceAssemblies =
ReferenceAssemblies.Default.AddPackages(ImmutableArray.Create(
new PackageIdentity("Azure.Core", "1.26.0"),
new PackageIdentity("Microsoft.Bcl.AsyncInterfaces", "1.1.0"),
new PackageIdentity("Azure.Core", "1.35.0"),
new PackageIdentity("Microsoft.Bcl.AsyncInterfaces", "1.1.1"),
new PackageIdentity("Newtonsoft.Json", "12.0.3"),
new PackageIdentity("System.Text.Json", "4.6.0"),
new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.3")));
new PackageIdentity("System.Text.Json", "4.7.2"),
new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.4")));

public static CSharpAnalyzerTest<TAnalyzer, XUnitVerifier> CreateAnalyzer(string source, LanguageVersion languageVersion = LanguageVersion.Latest)
=> new CSharpAnalyzerTest<TAnalyzer, XUnitVerifier>
public static CSharpAnalyzerTest<TAnalyzer, XUnitVerifier> CreateAnalyzer(string source, LanguageVersion languageVersion = LanguageVersion.Latest, Type[] additionalReferences = null)
{
var test = new CSharpAnalyzerTest<TAnalyzer, XUnitVerifier>
{
ReferenceAssemblies = DefaultReferenceAssemblies,
SolutionTransforms = {(solution, projectId) =>
Expand All @@ -37,9 +39,18 @@ public static CSharpAnalyzerTest<TAnalyzer, XUnitVerifier> CreateAnalyzer(string
TestCode = source,
TestBehaviors = TestBehaviors.SkipGeneratedCodeCheck
};
if (additionalReferences != null)
{
foreach (var reference in additionalReferences)
{
test.TestState.AdditionalReferences.Add(reference.Assembly);
}
}
return test;
}

public static Task VerifyAnalyzerAsync(string source, LanguageVersion languageVersion = LanguageVersion.Latest)
=> CreateAnalyzer(source, languageVersion).RunAsync(CancellationToken.None);
public static Task VerifyAnalyzerAsync(string source, LanguageVersion languageVersion = LanguageVersion.Latest, Type[] additionalReferences = null)
=> CreateAnalyzer(source, languageVersion, additionalReferences).RunAsync(CancellationToken.None);

public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] diagnostics)
{
Expand Down
Loading