Skip to content

Commit

Permalink
Merge pull request #5144 from jmarolf/RedundantPrivateCodeFixProvider
Browse files Browse the repository at this point in the history
Harden against null arguments in simplifier
Fixes #5121
  • Loading branch information
jmarolf committed Sep 11, 2015
2 parents e4a7be0 + 1eeffcf commit 4176470
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 1 deletion.
5 changes: 5 additions & 0 deletions docs/Breaking API Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ It was never the intent for these members to be a part of the supported API surf

PR: https://github.com/dotnet/roslyn/pull/4169

### Changed Simplifier methods to throw ArgumentNullExceptions
Changed Simplifier.ReduceAsync, Simplifier.ExpandAsync, and Simplifier.Expand methods to throw ArgumentNullExceptions if any non-optional, nullable arguments are passed in. Previously the user would get a NullReferenceException for synchronous methods and an AggregateException containing a NullReferenceException for asynchronous methods.

PR: https://github.com/dotnet/roslyn/pull/5144

1 change: 1 addition & 0 deletions src/EditorFeatures/Test2/EditorServicesTest2.vbproj
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
<Compile Include="Diagnostics\InMemoryAssemblyLoader.vb" />
<Compile Include="Diagnostics\UseAutoProperty\UseAutoPropertyTests.vb" />
<Compile Include="LanguageServices\SyntaxFactsServiceTests.vb" />
<Compile Include="Simplification\SimplifierAPITests.vb" />
<Compile Include="Utilities\MockDocumentNavigationServiceProvider.vb" />
<Compile Include="Utilities\MockSymbolNavigationServiceProvider.vb" />
<Compile Include="CodeFixes\CodeFixServiceTests.vb" />
Expand Down
163 changes: 163 additions & 0 deletions src/EditorFeatures/Test2/Simplification/SimplifierAPITests.vb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace
Imports Microsoft.CodeAnalysis.Simplification.Simplifier
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.UnitTests
Imports Microsoft.CodeAnalysis.VisualBasic.SyntaxFactory
Imports Xunit.Assert

Public Class SimplifierAPITests
Inherits WorkspaceTestBase

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestExpandAsync()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = ExpandAsync(Of SyntaxNode)(Nothing, Nothing).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "node"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestExpandAsync2()
Dim node = GetSyntaxNode()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = ExpandAsync(node, Nothing).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestExpand()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = Expand(Of SyntaxNode)(Nothing, Nothing, Nothing)
End Sub,
Sub(exception) Equal(exception.ParamName, "node"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestExpand2()
Dim node = GetSyntaxNode()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = Expand(node, Nothing, Nothing)
End Sub,
Sub(exception) Equal(exception.ParamName, "semanticModel"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestExpand3()
Dim node = GetSyntaxNode()
Dim semanticModel = GetSemanticModel()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = Expand(node, semanticModel, Nothing)
End Sub,
Sub(exception) Equal(exception.ParamName, "workspace"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestTokenExpandAsync()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = ExpandAsync(Nothing, Nothing).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestTokenExpand()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = Expand(Nothing, Nothing, Nothing)
End Sub,
Sub(exception) Equal(exception.ParamName, "semanticModel"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestTokenExpand2()
Dim semanticModel = GetSemanticModel()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim expandedNode = Expand(Nothing, semanticModel, Nothing)
End Sub,
Sub(exception) Equal(exception.ParamName, "workspace"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(Nothing).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync2()
Dim syntaxAnnotation As SyntaxAnnotation = Nothing
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(Nothing, syntaxAnnotation).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync3()
Dim syntaxAnnotation As SyntaxAnnotation = Nothing
Dim document = GetDocument()
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(document, syntaxAnnotation).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "annotation"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync4()
Dim textSpan As TextSpan = Nothing
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(Nothing, textSpan).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync5()
Dim spans As IEnumerable(Of TextSpan) = Nothing
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(Nothing, spans).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "document"))
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Formatting)>
Public Sub TestReduceAsync6()
Dim document = GetDocument()
Dim spans As IEnumerable(Of TextSpan) = Nothing
AssertThrows(Of ArgumentNullException)(
Sub()
Dim simplifiedNode = ReduceAsync(document, spans).Result
End Sub,
Sub(exception) Equal(exception.ParamName, "spans"))
End Sub

Private Function GetDocument() As Document
CreateFiles(GetSimpleCSharpSolutionFiles())
Dim sol = Create(properties:=New Dictionary(Of String, String) From {{"Configuration", "Release"}}).OpenSolutionAsync(GetSolutionFileName("TestSolution.sln")).Result
Return sol.Projects.First.Documents.First
End Function

Private Function GetSemanticModel() As SemanticModel
Return GetDocument().GetSemanticModelAsync().Result
End Function

Private Function GetSyntaxNode() As SyntaxNode
Return IdentifierName(Identifier("Test"))
End Function
End Class
70 changes: 70 additions & 0 deletions src/Workspaces/Core/Portable/Simplification/Simplifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public static partial class Simplifier
/// </summary>
public static async Task<TNode> ExpandAsync<TNode>(TNode node, Document document, Func<SyntaxNode, bool> expandInsideNode = null, bool expandParameter = false, CancellationToken cancellationToken = default(CancellationToken)) where TNode : SyntaxNode
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}

if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
return Expand(node, semanticModel, document.Project.Solution.Workspace, expandInsideNode, expandParameter, cancellationToken);
}
Expand All @@ -56,6 +66,21 @@ public static partial class Simplifier
/// </summary>
public static TNode Expand<TNode>(TNode node, SemanticModel semanticModel, Workspace workspace, Func<SyntaxNode, bool> expandInsideNode = null, bool expandParameter = false, CancellationToken cancellationToken = default(CancellationToken)) where TNode : SyntaxNode
{
if (node == null)
{
throw new ArgumentNullException(nameof(node));
}

if (semanticModel == null)
{
throw new ArgumentNullException(nameof(semanticModel));
}

if (workspace == null)
{
throw new ArgumentNullException(nameof(workspace));
}

var result = workspace.Services.GetLanguageServices(node.Language).GetService<ISimplificationService>()
.Expand(node, semanticModel, annotationForReplacedAliasIdentifier: null, expandInsideNode: expandInsideNode, expandParameter: expandParameter, cancellationToken: cancellationToken);

Expand All @@ -67,6 +92,11 @@ public static partial class Simplifier
/// </summary>
public static async Task<SyntaxToken> ExpandAsync(SyntaxToken token, Document document, Func<SyntaxNode, bool> expandInsideNode = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
return Expand(token, semanticModel, document.Project.Solution.Workspace, expandInsideNode, cancellationToken);
}
Expand All @@ -76,6 +106,16 @@ public static async Task<SyntaxToken> ExpandAsync(SyntaxToken token, Document do
/// </summary>
public static SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel, Workspace workspace, Func<SyntaxNode, bool> expandInsideNode = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (semanticModel == null)
{
throw new ArgumentNullException(nameof(semanticModel));
}

if (workspace == null)
{
throw new ArgumentNullException(nameof(workspace));
}

return workspace.Services.GetLanguageServices(token.Language).GetService<ISimplificationService>()
.Expand(token, semanticModel, expandInsideNode, cancellationToken);
}
Expand All @@ -85,6 +125,11 @@ public static SyntaxToken Expand(SyntaxToken token, SemanticModel semanticModel,
/// </summary>
public static async Task<Document> ReduceAsync(Document document, OptionSet optionSet = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
return await ReduceAsync(document, root.FullSpan, optionSet, cancellationToken).ConfigureAwait(false);
}
Expand All @@ -95,6 +140,16 @@ public static async Task<Document> ReduceAsync(Document document, OptionSet opti
/// </summary>
public static async Task<Document> ReduceAsync(Document document, SyntaxAnnotation annotation, OptionSet optionSet = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

if (annotation == null)
{
throw new ArgumentNullException(nameof(annotation));
}

var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
return await ReduceAsync(document, root.GetAnnotatedNodesAndTokens(annotation).Select(t => t.FullSpan), optionSet, cancellationToken).ConfigureAwait(false);
}
Expand All @@ -105,6 +160,11 @@ public static async Task<Document> ReduceAsync(Document document, SyntaxAnnotati
/// </summary>
public static Task<Document> ReduceAsync(Document document, TextSpan span, OptionSet optionSet = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

return ReduceAsync(document, SpecializedCollections.SingletonEnumerable(span), optionSet, cancellationToken);
}

Expand All @@ -114,6 +174,16 @@ public static Task<Document> ReduceAsync(Document document, TextSpan span, Optio
/// </summary>
public static Task<Document> ReduceAsync(Document document, IEnumerable<TextSpan> spans, OptionSet optionSet = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}

if (spans == null)
{
throw new ArgumentNullException(nameof(spans));
}

return document.Project.LanguageServices.GetService<ISimplificationService>().ReduceAsync(document, spans, optionSet, cancellationToken: cancellationToken);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Workspaces/CoreTest/ServicesTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,4 @@
<Import Project="..\..\..\build\Targets\Roslyn.Toolsets.Xunit.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
</ImportGroup>
</Project>
</Project>

0 comments on commit 4176470

Please sign in to comment.