Skip to content

Commit

Permalink
[GH-142] - adding simplified InternalsVisibleTo("DynamicProxyGenAssem…
Browse files Browse the repository at this point in the history
…bly2") when System.Runtime.CompilerServices in scope
  • Loading branch information
tpodolak committed Mar 25, 2020
1 parent 1108c34 commit e13d04a
Show file tree
Hide file tree
Showing 19 changed files with 639 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using NSubstitute.Analyzers.Shared.Extensions;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;

Expand All @@ -14,27 +15,14 @@ internal static class AddInternalsVisibleToAttributeRefactoring
{
public static Task<Document> RefactorAsync(Document document, CompilationUnitSyntax compilationUnitSyntax, CancellationToken cancellationToken = default)
{
var addAttributeLists = compilationUnitSyntax.AddAttributeLists(
AttributeList(
AttributeTargetSpecifier(
Token(SyntaxKind.AssemblyKeyword)),
SingletonSeparatedList(
Attribute(
QualifiedName(
QualifiedName(
QualifiedName(
IdentifierName("System"),
IdentifierName("Runtime")),
IdentifierName("CompilerServices")),
IdentifierName("InternalsVisibleTo")),
AttributeArgumentList(
SingletonSeparatedList(
AttributeArgument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("DynamicProxyGenAssembly2")))))))));
var syntaxGenerator = SyntaxGenerator.GetGenerator(document);
var attributeList = syntaxGenerator.InternalVisibleToDynamicProxyAttributeList()
.To<AttributeListSyntax>()
.WithTarget(AttributeTargetSpecifier(
Token(SyntaxKind.AssemblyKeyword)));

return document.ReplaceNodeAsync(compilationUnitSyntax, addAttributeLists, CancellationToken.None);
var updatedCompilationUnitSyntax = compilationUnitSyntax.AddAttributeLists(attributeList);
return document.ReplaceNodeAsync(compilationUnitSyntax, updatedCompilationUnitSyntax, cancellationToken);
}

public static void RegisterCodeFix(CodeFixContext context, Diagnostic diagnostic, CompilationUnitSyntax compilationUnitSyntax)
Expand Down
10 changes: 10 additions & 0 deletions src/NSubstitute.Analyzers.Shared/Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace NSubstitute.Analyzers.Shared.Extensions
{
internal static class ObjectExtensions
{
public static T To<T>(this object source)
{
return (T)source;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace NSubstitute.Analyzers.Shared.Extensions
{
internal static class SyntaxGeneratorExtension
internal static class SyntaxGeneratorExtensions
{
public static SyntaxNode SubstituteForInvocationExpression(
this SyntaxGenerator syntaxGenerator,
Expand All @@ -21,5 +21,15 @@ public static SyntaxNode SubstituteForInvocationExpression(

return invocationExpression;
}

public static SyntaxNode InternalVisibleToDynamicProxyAttributeList(this SyntaxGenerator syntaxGenerator)
{
var attributeArguments =
syntaxGenerator.AttributeArgument(syntaxGenerator.LiteralExpression("DynamicProxyGenAssembly2"));

return syntaxGenerator.Attribute(
"System.Runtime.CompilerServices.InternalsVisibleTo",
attributeArguments);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.VisualBasic;
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
using NSubstitute.Analyzers.Shared.Extensions;
Expand All @@ -14,23 +16,19 @@ internal static class AddInternalsVisibleToAttributeRefactoring
{
public static Task<Document> RefactorAsync(Document document, CompilationUnitSyntax compilationUnitSyntax, CancellationToken cancellationToken = default)
{
var addAttributeLists = compilationUnitSyntax.AddAttributes(
AttributesStatement(SingletonList(
AttributeList(SingletonSeparatedList(Attribute(
AttributeTarget(Token(SyntaxKind.AssemblyKeyword)),
QualifiedName(
QualifiedName(
QualifiedName(
IdentifierName("System"),
IdentifierName("Runtime")),
IdentifierName("CompilerServices")),
IdentifierName("InternalsVisibleTo")),
ArgumentList(SingletonSeparatedList<ArgumentSyntax>(SimpleArgument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("DynamicProxyGenAssembly2")))))))))));
var syntaxGenerator = SyntaxGenerator.GetGenerator(document);
var attributeList = syntaxGenerator.InternalVisibleToDynamicProxyAttributeList()
.To<AttributeListSyntax>();

return document.ReplaceNodeAsync(compilationUnitSyntax, addAttributeLists, CancellationToken.None);
var assemblyAttributes = attributeList.Attributes.Select(attr =>
attr.WithTarget(AttributeTarget(Token(SyntaxKind.AssemblyKeyword))));

attributeList = attributeList.WithAttributes(SeparatedList(assemblyAttributes));

var updatedCompilationUnitSyntax =
compilationUnitSyntax.AddAttributes(AttributesStatement(SingletonList(attributeList)));

return document.ReplaceNodeAsync(compilationUnitSyntax, updatedCompilationUnitSyntax, cancellationToken);
}

public static void RegisterCodeFix(CodeFixContext context, Diagnostic diagnostic, CompilationUnitSyntax compilationUnitSyntax)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@ public abstract class InternalSetupSpecificationCodeFixProviderVerifier : CSharp
[InlineData(".FooBar()")]
[InlineData("[0]")]
public abstract Task AppendsInternalsVisibleTo_ToTopLevelCompilationUnit_WhenUsedWithInternalMember(string method, string call);

[CombinatoryTheory]
[InlineData]
public abstract Task AppendsInternalsVisibleToWithFullyQualifiedName_WhenUsedWithInternalMemberAndCompilerServicesNotImported(string method);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public void Test()
var newSource = $@"using NSubstitute;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
Expand All @@ -377,6 +377,57 @@ public void Test()
var x = substitute.{method}(){call};
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}

public override async Task AppendsInternalsVisibleToWithFullyQualifiedName_WhenUsedWithInternalMemberAndCompilerServicesNotImported(string method)
{
var oldSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = substitute.{method}().FooBar();
}}
}}
}}";

var newSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = substitute.{method}().FooBar();
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public void Test()
var newSource = $@"using NSubstitute;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
Expand All @@ -377,6 +377,57 @@ public void Test()
var x = {method}(substitute){call};
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}

public override async Task AppendsInternalsVisibleToWithFullyQualifiedName_WhenUsedWithInternalMemberAndCompilerServicesNotImported(string method)
{
var oldSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = {method}(substitute).FooBar();
}}
}}
}}";

var newSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = {method}(substitute).FooBar();
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ public void Test()
var newSource = $@"using NSubstitute;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
Expand All @@ -374,6 +374,57 @@ public void Test()
var x = substitute{call}.{method}(1);
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}

public override async Task AppendsInternalsVisibleToWithFullyQualifiedName_WhenUsedWithInternalMemberAndCompilerServicesNotImported(string method)
{
var oldSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = substitute.FooBar().{method}(1);
}}
}}
}}";

var newSource = $@"using NSubstitute;
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""OtherAssembly"")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""DynamicProxyGenAssembly2"")]
namespace MyNamespace
{{
public class Foo
{{
internal virtual int FooBar()
{{
return 1;
}}
}}
public class FooTests
{{
public void Test()
{{
var substitute = NSubstitute.Substitute.For<Foo>();
var x = substitute.FooBar().{method}(1);
}}
}}
}}";
await VerifyFix(oldSource, newSource, 2);
}
Expand Down
Loading

0 comments on commit e13d04a

Please sign in to comment.