Skip to content

Commit

Permalink
Merge pull request #53648 from dotnet/merges/main-to-main-vs-deps
Browse files Browse the repository at this point in the history
Merge main to main-vs-deps
  • Loading branch information
Cosifne authored May 25, 2021
2 parents c1394eb + f986fa9 commit a776edd
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Precedence;
Expand All @@ -24,19 +25,20 @@ protected override ISyntaxFacts GetSyntaxFacts()
=> CSharpSyntaxFacts.Instance;

protected override bool CanRemoveParentheses(
ParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel,
ParenthesizedExpressionSyntax parenthesizedExpression,
SemanticModel semanticModel, CancellationToken cancellationToken,
out PrecedenceKind precedence, out bool clarifiesPrecedence)
{
return CanRemoveParenthesesHelper(
parenthesizedExpression, semanticModel,
parenthesizedExpression, semanticModel, cancellationToken,
out precedence, out clarifiesPrecedence);
}

public static bool CanRemoveParenthesesHelper(
ParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel,
ParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel, CancellationToken cancellationToken,
out PrecedenceKind parentPrecedenceKind, out bool clarifiesPrecedence)
{
var result = parenthesizedExpression.CanRemoveParentheses(semanticModel);
var result = parenthesizedExpression.CanRemoveParentheses(semanticModel, cancellationToken);
if (!result)
{
parentPrecedenceKind = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageServices;
using Microsoft.CodeAnalysis.CSharp.Precedence;
Expand All @@ -24,17 +25,15 @@ protected override ISyntaxFacts GetSyntaxFacts()
=> CSharpSyntaxFacts.Instance;

protected override bool CanRemoveParentheses(
ParenthesizedPatternSyntax parenthesizedExpression, SemanticModel semanticModel,
ParenthesizedPatternSyntax parenthesizedExpression,
SemanticModel semanticModel, CancellationToken cancellationToken,
out PrecedenceKind precedence, out bool clarifiesPrecedence)
{
return CanRemoveParenthesesHelper(
parenthesizedExpression,
out precedence, out clarifiesPrecedence);
return CanRemoveParenthesesHelper(parenthesizedExpression, out precedence, out clarifiesPrecedence);
}

public static bool CanRemoveParenthesesHelper(
ParenthesizedPatternSyntax parenthesizedPattern,
out PrecedenceKind parentPrecedenceKind, out bool clarifiesPrecedence)
ParenthesizedPatternSyntax parenthesizedPattern, out PrecedenceKind parentPrecedenceKind, out bool clarifiesPrecedence)
{
var result = parenthesizedPattern.CanRemoveParentheses();
if (!result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

using System.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.RemoveUnnecessaryParentheses;
Expand All @@ -22,10 +23,10 @@ public CSharpRemoveUnnecessaryParenthesesCodeFixProvider()
{
}

protected override bool CanRemoveParentheses(SyntaxNode current, SemanticModel semanticModel)
protected override bool CanRemoveParentheses(SyntaxNode current, SemanticModel semanticModel, CancellationToken cancellationToken)
=> current switch
{
ParenthesizedExpressionSyntax p => CSharpRemoveUnnecessaryExpressionParenthesesDiagnosticAnalyzer.CanRemoveParenthesesHelper(p, semanticModel, out _, out _),
ParenthesizedExpressionSyntax p => CSharpRemoveUnnecessaryExpressionParenthesesDiagnosticAnalyzer.CanRemoveParenthesesHelper(p, semanticModel, cancellationToken, out _, out _),
ParenthesizedPatternSyntax p => CSharpRemoveUnnecessaryPatternParenthesesDiagnosticAnalyzer.CanRemoveParenthesesHelper(p, out _, out _),
_ => false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2626,5 +2626,53 @@ void M(object o)
}
}", offeredWhenRequireForClarityIsEnabled: true);
}

[WorkItem(50025, "https://github.com/dotnet/roslyn/issues/50025")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryParentheses)]
public async Task TestDoNotRemoveWithConstantAndTypeAmbiguity()
{
await TestMissingAsync(
@"
public class C
{
public const int Goo = 1;
public void M(Goo o)
{
if (o is $$(Goo)) M(1);
}
}
public class Goo { }");
}

[WorkItem(50025, "https://github.com/dotnet/roslyn/issues/50025")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryParentheses)]
public async Task TestDoRemoveWithNoConstantAndTypeAmbiguity()
{
await TestAsync(
@"
public class C
{
public const int Goo = 1;
public void M(object o)
{
if (o is $$(Goo)) M(1);
}
}
",
@"
public class C
{
public const int Goo = 1;
public void M(object o)
{
if (o is Goo) M(1);
}
}
", offeredWhenRequireForClarityIsEnabled: true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ protected sealed override void InitializeWorker(AnalysisContext context)
=> context.RegisterSyntaxNodeAction(AnalyzeSyntax, GetSyntaxKind());

protected abstract bool CanRemoveParentheses(
TParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel,
TParenthesizedExpressionSyntax parenthesizedExpression, SemanticModel semanticModel, CancellationToken cancellationToken,
out PrecedenceKind precedence, out bool clarifiesPrecedence);

private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
{
var cancellationToken = context.CancellationToken;
var parenthesizedExpression = (TParenthesizedExpressionSyntax)context.Node;

if (!CanRemoveParentheses(parenthesizedExpression, context.SemanticModel,
if (!CanRemoveParentheses(parenthesizedExpression, context.SemanticModel, cancellationToken,
out var precedence, out var clarifiesPrecedence))
{
return;
Expand Down Expand Up @@ -112,7 +113,7 @@ private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)

context.ReportDiagnostic(DiagnosticHelper.CreateWithLocationTags(
Descriptor,
GetDiagnosticSquiggleLocation(parenthesizedExpression, context.CancellationToken),
AbstractRemoveUnnecessaryParenthesesDiagnosticAnalyzer<TLanguageKindEnum, TParenthesizedExpressionSyntax>.GetDiagnosticSquiggleLocation(parenthesizedExpression, cancellationToken),
severity,
additionalLocations,
additionalUnnecessaryLocations));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public override ImmutableArray<string> FixableDiagnosticIds

internal sealed override CodeFixCategory CodeFixCategory => CodeFixCategory.CodeStyle;

protected abstract bool CanRemoveParentheses(TParenthesizedExpressionSyntax current, SemanticModel semanticModel);
protected abstract bool CanRemoveParentheses(
TParenthesizedExpressionSyntax current, SemanticModel semanticModel, CancellationToken cancellationToken);

public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
Expand All @@ -48,7 +49,7 @@ protected override Task FixAllAsync(

return editor.ApplyExpressionLevelSemanticEditsAsync(
document, originalNodes,
(semanticModel, current) => current != null && CanRemoveParentheses(current, semanticModel),
(semanticModel, current) => current != null && CanRemoveParentheses(current, semanticModel, cancellationToken),
(_, currentRoot, current) => currentRoot.ReplaceNode(current, syntaxFacts.Unparenthesize(current)),
cancellationToken);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryParentheses
Imports Microsoft.CodeAnalysis.Precedence
Imports Microsoft.CodeAnalysis.LanguageServices
Imports System.Threading

Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryParentheses
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Expand All @@ -24,7 +25,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryParentheses
End Function

Protected Overrides Function CanRemoveParentheses(
parenthesizedExpression As ParenthesizedExpressionSyntax, semanticModel As SemanticModel,
parenthesizedExpression As ParenthesizedExpressionSyntax,
semanticModel As SemanticModel, cancellationToken As CancellationToken,
ByRef precedence As PrecedenceKind, ByRef clarifiesPrecedence As Boolean) As Boolean

Return CanRemoveParenthesesHelper(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

Imports System.Composition
Imports System.Diagnostics.CodeAnalysis
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryParentheses
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Expand All @@ -18,7 +19,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryParentheses
Public Sub New()
End Sub

Protected Overrides Function CanRemoveParentheses(current As ParenthesizedExpressionSyntax, semanticModel As SemanticModel) As Boolean
Protected Overrides Function CanRemoveParentheses(current As ParenthesizedExpressionSyntax, semanticModel As SemanticModel, cancellationtoken As CancellationToken) As Boolean
Return VisualBasicRemoveUnnecessaryParenthesesDiagnosticAnalyzer.CanRemoveParenthesesHelper(
current, semanticModel, precedence:=Nothing, clarifiesPrecedence:=Nothing)
End Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
Expand Down Expand Up @@ -33,7 +31,7 @@ private static SyntaxNode SimplifyParentheses(
OptionSet optionSet,
CancellationToken cancellationToken)
{
if (node.CanRemoveParentheses(semanticModel))
if (node.CanRemoveParentheses(semanticModel, cancellationToken))
{
// TODO(DustinCa): We should not be skipping elastic trivia below.
// However, the formatter seems to mess up trailing trivia in some
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Extensions;
using Microsoft.CodeAnalysis.PooledObjects;
Expand All @@ -16,7 +17,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Extensions
{
internal static class ParenthesizedExpressionSyntaxExtensions
{
public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node, SemanticModel semanticModel)
public static bool CanRemoveParentheses(
this ParenthesizedExpressionSyntax node, SemanticModel semanticModel, CancellationToken cancellationToken)
{
if (node.OpenParenToken.IsMissing || node.CloseParenToken.IsMissing)
{
Expand Down Expand Up @@ -136,7 +138,8 @@ public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node,
// Handle expression-level ambiguities
if (RemovalMayIntroduceCastAmbiguity(node) ||
RemovalMayIntroduceCommaListAmbiguity(node) ||
RemovalMayIntroduceInterpolationAmbiguity(node))
RemovalMayIntroduceInterpolationAmbiguity(node) ||
RemovalWouldChangeConstantReferenceToTypeReference(node, expression, semanticModel, cancellationToken))
{
return false;
}
Expand Down Expand Up @@ -306,6 +309,24 @@ public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node,
return parentExpression != null && !RemovalChangesAssociation(node, parentExpression, semanticModel);
}

private static bool RemovalWouldChangeConstantReferenceToTypeReference(
ParenthesizedExpressionSyntax node, ExpressionSyntax expression,
SemanticModel semanticModel, CancellationToken cancellationToken)
{
// With cases like: `if (x is (Y))` then we cannot remove the parens if it would make Y now bind to a type
// instead of a constant.
if (node.Parent is not ConstantPatternSyntax { Parent: IsPatternExpressionSyntax })
return false;

var exprSymbol = semanticModel.GetSymbolInfo(expression, cancellationToken).Symbol;
if (exprSymbol is not IFieldSymbol { IsConst: true } field)
return false;

// See if interpreting the same expression as a type in this location binds.
var potentialType = semanticModel.GetSpeculativeTypeInfo(expression.SpanStart, expression, SpeculativeBindingOption.BindAsTypeOrNamespace).Type;
return potentialType is not (null or IErrorTypeSymbol);
}

private static readonly ObjectPool<Stack<SyntaxNode>> s_nodeStackPool = SharedPools.Default<Stack<SyntaxNode>>();

private static bool RemovalMayIntroduceInterpolationAmbiguity(ParenthesizedExpressionSyntax node)
Expand Down Expand Up @@ -668,12 +689,7 @@ private static bool IsNextExpressionPotentiallyAmbiguous(ExpressionSyntax node)
}

private static bool IsSimpleOrDottedName(ExpressionSyntax expression)
{
return expression.IsKind(
SyntaxKind.IdentifierName,
SyntaxKind.QualifiedName,
SyntaxKind.SimpleMemberAccessExpression);
}
=> expression.Kind() is SyntaxKind.IdentifierName or SyntaxKind.QualifiedName or SyntaxKind.SimpleMemberAccessExpression;

public static bool CanRemoveParentheses(this ParenthesizedPatternSyntax node)
{
Expand Down

0 comments on commit a776edd

Please sign in to comment.