private static SyntaxKind GetInvertedOperatorKind(SyntaxToken operatorToken) { switch (operatorToken.Kind()) { case SyntaxKind.AmpersandAmpersandToken: return(SyntaxKind.BarBarToken); case SyntaxKind.BarBarToken: return(SyntaxKind.AmpersandAmpersandToken); case SyntaxKind.EqualsEqualsToken: return(SyntaxKind.ExclamationEqualsToken); case SyntaxKind.ExclamationEqualsToken: return(SyntaxKind.EqualsEqualsToken); case SyntaxKind.GreaterThanToken: return(SyntaxKind.LessThanEqualsToken); case SyntaxKind.GreaterThanEqualsToken: return(SyntaxKind.LessThanToken); case SyntaxKind.LessThanToken: return(SyntaxKind.GreaterThanEqualsToken); case SyntaxKind.LessThanEqualsToken: return(SyntaxKind.GreaterThanToken); default: { SyntaxDebug.Fail(operatorToken); return(operatorToken.Kind()); } } }
private static TypeSyntax GetTypeSyntax(SyntaxNode node) { switch (node) { case EventDeclarationSyntax eventDeclaration: { return(eventDeclaration.Type); } case VariableDeclaratorSyntax declarator: { if (declarator.Parent is VariableDeclarationSyntax declaration) { return(declaration.Type); } SyntaxDebug.Fail(declarator.Parent); break; } default: { SyntaxDebug.Fail(node); break; } } return(null); }
private static async Task <Document> UseStringLengthInsteadOfComparisonWithEmptyStringAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; BinaryExpressionSyntax newNode; if (CSharpUtility.IsEmptyStringExpression(left, semanticModel, cancellationToken)) { newNode = binaryExpression .WithLeft(NumericLiteralExpression(0)) .WithRight(CreateConditionalAccess(right)); } else if (CSharpUtility.IsEmptyStringExpression(right, semanticModel, cancellationToken)) { newNode = binaryExpression .WithLeft(CreateConditionalAccess(left)) .WithRight(NumericLiteralExpression(0)); } else { SyntaxDebug.Fail(binaryExpression); return(document); } newNode = newNode.WithTriviaFrom(binaryExpression).WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { switch (node.Expression) { case SimpleNameSyntax simpleName: { AnalyzeSimpleName(simpleName); break; } case MemberBindingExpressionSyntax memberBindingExpression: { AnalyzeSimpleName(memberBindingExpression.Name); break; } case MemberAccessExpressionSyntax memberAccessExpression: { AnalyzeSimpleName(memberAccessExpression.Name); break; } default: { SyntaxDebug.Fail(node); break; } } base.VisitInvocationExpression(node); }
public static async Task <Document> RefactorAsync( Document document, AccessorListSyntax accessorList, CancellationToken cancellationToken) { if (accessorList.Accessors.All(f => f.BodyOrExpressionBody() == null)) { SyntaxNode parent = accessorList.Parent; switch (parent) { case PropertyDeclarationSyntax propertyDeclaration: { TextSpan span = TextSpan.FromBounds( propertyDeclaration.Identifier.Span.End, accessorList.CloseBraceToken.SpanStart); PropertyDeclarationSyntax newNode = propertyDeclaration.RemoveWhitespace(span); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken).ConfigureAwait(false)); } case IndexerDeclarationSyntax indexerDeclaration: { TextSpan span = TextSpan.FromBounds( indexerDeclaration.ParameterList.CloseBracketToken.Span.End, accessorList.CloseBraceToken.SpanStart); IndexerDeclarationSyntax newNode = indexerDeclaration.RemoveWhitespace(span); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(indexerDeclaration, newNode, cancellationToken).ConfigureAwait(false)); } default: { SyntaxDebug.Fail(parent); return(document); } } } else { AccessorListSyntax newAccessorList = GetNewAccessorList(accessorList); newAccessorList = AddNewLineAfterFirstAccessorIfNecessary(accessorList, newAccessorList, cancellationToken); newAccessorList = newAccessorList.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(accessorList, newAccessorList, cancellationToken).ConfigureAwait(false)); } }
public static Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; ExpressionSyntax newNode = binaryExpression; TextSpan span = TextSpan.FromBounds(left.Span.End, right.SpanStart); IEnumerable <SyntaxTrivia> trivia = binaryExpression.DescendantTrivia(span); bool isWhiteSpaceOrEndOfLine = trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()); if (IsBooleanLiteralExpression(left.Kind())) { SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia(); if (!isWhiteSpaceOrEndOfLine) { leadingTrivia = leadingTrivia.AddRange(trivia); } newNode = right.WithLeadingTrivia(leadingTrivia); } else if (IsBooleanLiteralExpression(right.Kind())) { SyntaxTriviaList trailingTrivia = binaryExpression.GetTrailingTrivia(); if (!isWhiteSpaceOrEndOfLine) { trailingTrivia = trailingTrivia.InsertRange(0, trivia); } newNode = left.WithTrailingTrivia(trailingTrivia); } else { SyntaxDebug.Fail(binaryExpression); } return(document.ReplaceNodeAsync(binaryExpression, newNode.WithFormatterAnnotation(), cancellationToken)); }
private static InvocationExpressionSyntax GetNewInvocation(InvocationExpressionSyntax invocation) { ExpressionSyntax expression = invocation.Expression; ArgumentListSyntax argumentList = invocation.ArgumentList; SeparatedSyntaxList <ArgumentSyntax> arguments = argumentList.Arguments; ArgumentSyntax argument = arguments[0]; MemberAccessExpressionSyntax newMemberAccess = CreateNewMemberAccessExpression(); if (newMemberAccess == null) { return(null); } return(invocation .WithExpression(newMemberAccess) .WithArgumentList(argumentList.WithArguments(arguments.Remove(argument)))); MemberAccessExpressionSyntax CreateNewMemberAccessExpression() { switch (expression.Kind()) { case SyntaxKind.IdentifierName: case SyntaxKind.GenericName: { return(SimpleMemberAccessExpression( ParenthesizedExpression(argument.Expression), (SimpleNameSyntax)expression)); } case SyntaxKind.SimpleMemberAccessExpression: { var memberAccess = (MemberAccessExpressionSyntax)expression; return(memberAccess.WithExpression(ParenthesizedExpression(argument.Expression))); } default: { SyntaxDebug.Fail(expression); return(null); } } } }
public override bool CanBeRenamed(SyntaxToken token) { switch (token.Kind()) { case SyntaxKind.IdentifierToken: return(true); case SyntaxKind.ThisKeyword: case SyntaxKind.BaseKeyword: case SyntaxKind.GetKeyword: case SyntaxKind.SetKeyword: case SyntaxKind.AddKeyword: case SyntaxKind.RemoveKeyword: return(false); } SyntaxDebug.Fail(token); return(false); }
private static SyntaxKind GetBinaryExpressionKind(AssignmentExpressionSyntax assignmentExpression) { switch (assignmentExpression.Kind()) { case SyntaxKind.AddAssignmentExpression: return(SyntaxKind.AddExpression); case SyntaxKind.SubtractAssignmentExpression: return(SyntaxKind.SubtractExpression); case SyntaxKind.MultiplyAssignmentExpression: return(SyntaxKind.MultiplyExpression); case SyntaxKind.DivideAssignmentExpression: return(SyntaxKind.DivideExpression); case SyntaxKind.ModuloAssignmentExpression: return(SyntaxKind.ModuloExpression); case SyntaxKind.AndAssignmentExpression: return(SyntaxKind.BitwiseAndExpression); case SyntaxKind.OrAssignmentExpression: return(SyntaxKind.BitwiseOrExpression); case SyntaxKind.ExclusiveOrAssignmentExpression: return(SyntaxKind.ExclusiveOrExpression); case SyntaxKind.LeftShiftAssignmentExpression: return(SyntaxKind.LeftShiftExpression); case SyntaxKind.RightShiftAssignmentExpression: return(SyntaxKind.RightShiftExpression); } SyntaxDebug.Fail(assignmentExpression); return(SyntaxKind.None); }
private static (ISymbol symbol, ITypeSymbol typeSymbol) GetContainingSymbolAndType( ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken = default) { switch (semanticModel.GetEnclosingSymbol(expression.SpanStart, cancellationToken)) { case IMethodSymbol methodSymbol: { MethodKind methodKind = methodSymbol.MethodKind; if (methodKind == MethodKind.PropertyGet) { var propertySymbol = (IPropertySymbol)methodSymbol.AssociatedSymbol; return(propertySymbol, propertySymbol.Type); } if (methodKind == MethodKind.Ordinary && methodSymbol.PartialImplementationPart != null) { methodSymbol = methodSymbol.PartialImplementationPart; } return(methodSymbol, methodSymbol.ReturnType); } case IFieldSymbol fieldSymbol: { return(fieldSymbol, fieldSymbol.Type); } } SyntaxDebug.Fail(expression); return(default((ISymbol, ITypeSymbol))); }
private static void AnalyzeNameEquals(SyntaxNodeAnalysisContext context) { var node = (NameEqualsSyntax)context.Node; switch (node.Parent.Kind()) { case SyntaxKind.AttributeArgument: { var attributeArgument = (AttributeArgumentSyntax)node.Parent; Analyze(context, attributeArgument.NameEquals.EqualsToken, attributeArgument.Expression); break; } case SyntaxKind.AnonymousObjectMemberDeclarator: { var declarator = (AnonymousObjectMemberDeclaratorSyntax)node.Parent; Analyze(context, declarator.NameEquals.EqualsToken, declarator.Expression); break; } case SyntaxKind.UsingDirective: { var usingDirective = (UsingDirectiveSyntax)node.Parent; Analyze(context, usingDirective.Alias.EqualsToken, usingDirective.Name); break; } default: { SyntaxDebug.Fail(node.Parent); break; } } }
public override SyntaxNode VisitYieldStatement(YieldStatementSyntax node) { SyntaxToken keyword = node.ReturnOrBreakKeyword; ExpressionSyntax expression = node.Expression; SyntaxKind kind = node.Kind(); if (kind == SyntaxKind.YieldReturnStatement) { ParenthesizedExpressionSyntax parenthesizedExpression = expression.Parenthesize(); CastExpressionSyntax castExpression = CastExpression( _typeSymbol.ToMinimalTypeSyntax(_semanticModel, node.SpanStart), parenthesizedExpression); InvocationExpressionSyntax invocationExpression = SimpleMemberInvocationExpression( _identifierName, _addName, Argument(castExpression.WithSimplifierAnnotation())); return(ExpressionStatement(invocationExpression.WithoutTrivia()) .WithTriviaFrom(node) .AppendToLeadingTrivia(node.DescendantTrivia(TextSpan.FromBounds(keyword.Span.End, expression.SpanStart)))); } else if (kind == SyntaxKind.YieldBreakStatement) { return(ReturnStatement( Token(keyword.LeadingTrivia, SyntaxKind.ReturnKeyword, keyword.TrailingTrivia), _identifierName, node.SemicolonToken)); } SyntaxDebug.Fail(node); return(base.VisitYieldStatement(node)); }
internal static bool IsFixable( PropertyDeclarationSyntax propertyDeclaration, AccessorDeclarationSyntax accessor, SemanticModel semanticModel, CancellationToken cancellationToken) { switch (accessor.Kind()) { case SyntaxKind.GetAccessorDeclaration: { ExpressionSyntax expression = GetGetAccessorExpression(accessor); if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) != true) { return(false); } var memberAccess = (MemberAccessExpressionSyntax)expression; if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } SimpleNameSyntax simpleName = memberAccess.Name; IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol)); } case SyntaxKind.SetAccessorDeclaration: { ExpressionSyntax expression = GetSetAccessorExpression(accessor); SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!assignment.Success) { return(false); } if (assignment.Left.Kind() != SyntaxKind.SimpleMemberAccessExpression) { return(false); } var memberAccess = (MemberAccessExpressionSyntax)assignment.Left; if (memberAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (assignment.Right.Kind() != SyntaxKind.IdentifierName) { return(false); } var identifierName = (IdentifierNameSyntax)assignment.Right; if (identifierName.Identifier.ValueText != "value") { return(false); } SimpleNameSyntax simpleName = memberAccess.Name; if (simpleName == null) { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(simpleName, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol)); } case SyntaxKind.UnknownAccessorDeclaration: { return(false); } default: { SyntaxDebug.Fail(accessor); return(false); } } }
private static SyntaxNode Refactor(SyntaxNode node) { switch (node.Kind()) { case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(methodDeclaration.Body); return(methodDeclaration .WithExpressionBody(CreateExpressionBody(analysis, methodDeclaration)) .WithSemicolonToken(CreateSemicolonToken(methodDeclaration.Body, analysis)) .WithBody(null)); } case SyntaxKind.ConstructorDeclaration: { var constructorDeclaration = (ConstructorDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(constructorDeclaration.Body); return(constructorDeclaration .WithExpressionBody(CreateExpressionBody(analysis, constructorDeclaration)) .WithSemicolonToken(CreateSemicolonToken(constructorDeclaration.Body, analysis)) .WithBody(null)); } case SyntaxKind.DestructorDeclaration: { var destructorDeclaration = (DestructorDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(destructorDeclaration.Body); return(destructorDeclaration .WithExpressionBody(CreateExpressionBody(analysis, destructorDeclaration)) .WithSemicolonToken(CreateSemicolonToken(destructorDeclaration.Body, analysis)) .WithBody(null)); } case SyntaxKind.LocalFunctionStatement: { var localFunction = (LocalFunctionStatementSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(localFunction.Body); return(localFunction .WithExpressionBody(CreateExpressionBody(analysis, localFunction)) .WithSemicolonToken(CreateSemicolonToken(localFunction.Body, analysis)) .WithBody(null)); } case SyntaxKind.OperatorDeclaration: { var operatorDeclaration = (OperatorDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body); return(operatorDeclaration .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration)) .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis)) .WithBody(null)); } case SyntaxKind.ConversionOperatorDeclaration: { var operatorDeclaration = (ConversionOperatorDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(operatorDeclaration.Body); return(operatorDeclaration .WithExpressionBody(CreateExpressionBody(analysis, operatorDeclaration)) .WithSemicolonToken(CreateSemicolonToken(operatorDeclaration.Body, analysis)) .WithBody(null)); } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(propertyDeclaration.AccessorList); return(propertyDeclaration .WithExpressionBody(CreateExpressionBody(analysis, propertyDeclaration)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithAccessorList(null)); } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(indexerDeclaration.AccessorList); return(indexerDeclaration .WithExpressionBody(CreateExpressionBody(analysis, indexerDeclaration)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithAccessorList(null)); } case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.InitAccessorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: { var accessor = (AccessorDeclarationSyntax)node; BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(accessor); return(accessor .WithExpressionBody(CreateExpressionBody(analysis, accessor)) .WithSemicolonToken(CreateSemicolonToken(analysis.Block, analysis)) .WithBody(null)); } default: { SyntaxDebug.Fail(node); return(node); } } }
private static async Task <Document> RefactorAsync( Document document, ConditionalAccessExpressionSyntax conditionalAccess, CancellationToken cancellationToken) { ExpressionSyntax expression = conditionalAccess.Expression; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); int position = conditionalAccess.SpanStart; string localName = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.Variable, semanticModel, position); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, cancellationToken); TypeSyntax type = (typeSymbol?.SupportsExplicitDeclaration() == true) ? typeSymbol.ToMinimalTypeSyntax(semanticModel, position) : VarType(); LocalDeclarationStatementSyntax localStatement = LocalDeclarationStatement( type, Identifier(localName).WithRenameAnnotation(), expression); ExpressionSyntax newExpression = ReturnCompletedTaskInsteadOfNullCodeFixProvider.CreateCompletedTaskExpression(document, conditionalAccess, semanticModel, cancellationToken); IfStatementSyntax ifStatement = IfStatement( NotEqualsExpression(IdentifierName(localName), NullLiteralExpression()), Block(ReturnStatement(conditionalAccess .WithExpression(IdentifierName(localName).WithTriviaFrom(conditionalAccess.Expression)) .RemoveOperatorToken())), ElseClause(Block(ReturnStatement(newExpression)))); SyntaxList <StatementSyntax> statements = List(new StatementSyntax[] { localStatement, ifStatement }); SyntaxNode parent = conditionalAccess.Parent; if (parent is ReturnStatementSyntax returnStatement) { statements = statements.WithTriviaFrom(returnStatement); if (returnStatement.IsEmbedded()) { return(await document.ReplaceNodeAsync(returnStatement, Block(statements), cancellationToken).ConfigureAwait(false)); } else { return(await document.ReplaceNodeAsync(returnStatement, statements, cancellationToken).ConfigureAwait(false)); } } else if (parent is SimpleLambdaExpressionSyntax simpleLambda) { SimpleLambdaExpressionSyntax newNode = simpleLambda .WithBody(Block(statements)) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(simpleLambda, newNode, cancellationToken).ConfigureAwait(false)); } else if (parent is ParenthesizedLambdaExpressionSyntax parenthesizedLambda) { ParenthesizedLambdaExpressionSyntax newNode = parenthesizedLambda .WithBody(Block(statements)) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(parenthesizedLambda, newNode, cancellationToken).ConfigureAwait(false)); } else { var arrowExpressionClause = (ArrowExpressionClauseSyntax)parent; SyntaxNode node = arrowExpressionClause.Parent; SyntaxNode newNode = CreateNewNode(node).WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(node, newNode, cancellationToken).ConfigureAwait(false)); } SyntaxNode CreateNewNode(SyntaxNode node) { switch (node) { case MethodDeclarationSyntax methodDeclaration: { return(methodDeclaration .WithExpressionBody(null) .WithBody(Block(statements))); } case LocalFunctionStatementSyntax localFunction: { return(localFunction .WithExpressionBody(null) .WithBody(Block(statements))); } case PropertyDeclarationSyntax propertyDeclaration: { return(propertyDeclaration .WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken)) .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements))))); } case IndexerDeclarationSyntax indexerDeclaration: { return(indexerDeclaration .WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken)) .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements))))); } case AccessorDeclarationSyntax accessorDeclaration: { return(accessorDeclaration .WithExpressionBody(null) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block(statements))); } default: { SyntaxDebug.Fail(node); return(node); } } } }
private static void AnalyzeSingleLineDocumentationCommentTrivia(SyntaxNodeAnalysisContext context) { var documentationComment = (DocumentationCommentTriviaSyntax)context.Node; if (!documentationComment.IsPartOfMemberDeclaration()) { return; } bool?useCorrectDocumentationTagEnabled = null; var containsInheritDoc = false; var containsIncludeOrExclude = false; var containsSummaryElement = false; var containsContentElement = false; var isFirst = true; CancellationToken cancellationToken = context.CancellationToken; SyntaxList <XmlNodeSyntax> content = documentationComment.Content; for (int i = 0; i < content.Count; i++) { cancellationToken.ThrowIfCancellationRequested(); XmlElementInfo info = SyntaxInfo.XmlElementInfo(content[i]); if (info.Success) { switch (info.GetTag()) { case XmlTag.Include: case XmlTag.Exclude: { if (isFirst) { containsIncludeOrExclude = true; } break; } case XmlTag.InheritDoc: { containsInheritDoc = true; break; } case XmlTag.Content: { containsContentElement = true; break; } case XmlTag.Summary: { if (info.IsContentEmptyOrWhitespace) { ReportDiagnosticIfEffective(context, DiagnosticRules.AddSummaryToDocumentationComment, info.Element); } containsSummaryElement = true; if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context)) { FixDocumentationCommentTagAnalysis.Analyze(context, info); } break; } case XmlTag.Example: case XmlTag.Remarks: case XmlTag.Returns: case XmlTag.Value: { if (info.IsContentEmptyOrWhitespace) { ReportUnusedElement(context, info.Element, i, content); } if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context)) { FixDocumentationCommentTagAnalysis.Analyze(context, info); } break; } case XmlTag.Exception: case XmlTag.List: case XmlTag.Param: case XmlTag.Permission: case XmlTag.TypeParam: { if (useCorrectDocumentationTagEnabled ??= DiagnosticRules.FixDocumentationCommentTag.IsEffective(context)) { FixDocumentationCommentTagAnalysis.Analyze(context, info); } break; } case XmlTag.C: case XmlTag.Code: case XmlTag.Para: case XmlTag.ParamRef: case XmlTag.See: case XmlTag.SeeAlso: case XmlTag.TypeParamRef: { break; } default: { SyntaxDebug.Fail(content[i]); break; } } if (isFirst) { isFirst = false; } else { containsIncludeOrExclude = false; } } } if (containsInheritDoc || containsIncludeOrExclude) { return; } if (!containsSummaryElement && !containsContentElement) { ReportDiagnosticIfEffective(context, DiagnosticRules.AddSummaryElementToDocumentationComment, documentationComment); } SyntaxNode parent = documentationComment.ParentTrivia.Token.Parent; bool unusedElement = DiagnosticRules.UnusedElementInDocumentationComment.IsEffective(context); bool orderParams = DiagnosticRules.OrderElementsInDocumentationComment.IsEffective(context); bool addParam = DiagnosticRules.AddParamElementToDocumentationComment.IsEffective(context); bool addTypeParam = DiagnosticRules.AddTypeParamElementToDocumentationComment.IsEffective(context); if (addParam || orderParams || unusedElement) { SeparatedSyntaxList <ParameterSyntax> parameters = CSharpUtility.GetParameters( (parent is MemberDeclarationSyntax) ? parent : parent.Parent); if (addParam && parameters.Any()) { foreach (ParameterSyntax parameter in parameters) { if (IsMissing(documentationComment, parameter)) { ReportDiagnostic(context, DiagnosticRules.AddParamElementToDocumentationComment, documentationComment); break; } } } if (orderParams || unusedElement) { Analyze(context, documentationComment.Content, parameters, XmlTag.Param, (nodes, name) => nodes.IndexOf(name)); } } if (addTypeParam || orderParams || unusedElement) { SeparatedSyntaxList <TypeParameterSyntax> typeParameters = CSharpUtility.GetTypeParameters( (parent is MemberDeclarationSyntax) ? parent : parent.Parent); if (addTypeParam && typeParameters.Any()) { foreach (TypeParameterSyntax typeParameter in typeParameters) { if (IsMissing(documentationComment, typeParameter)) { ReportDiagnostic(context, DiagnosticRules.AddTypeParamElementToDocumentationComment, documentationComment); break; } } } if (orderParams || unusedElement) { Analyze(context, documentationComment.Content, typeParameters, XmlTag.TypeParam, (nodes, name) => nodes.IndexOf(name)); } } }
public virtual void VisitStatement(StatementSyntax node) { switch (node.Kind()) { case SyntaxKind.Block: { VisitBlock((BlockSyntax)node); break; } case SyntaxKind.BreakStatement: { VisitBreakStatement((BreakStatementSyntax)node); break; } case SyntaxKind.ContinueStatement: { VisitContinueStatement((ContinueStatementSyntax)node); break; } case SyntaxKind.DoStatement: { VisitDoStatement((DoStatementSyntax)node); break; } case SyntaxKind.EmptyStatement: { VisitEmptyStatement((EmptyStatementSyntax)node); break; } case SyntaxKind.ExpressionStatement: { VisitExpressionStatement((ExpressionStatementSyntax)node); break; } case SyntaxKind.FixedStatement: { VisitFixedStatement((FixedStatementSyntax)node); break; } case SyntaxKind.ForEachStatement: { VisitForEachStatement((ForEachStatementSyntax)node); break; } case SyntaxKind.ForEachVariableStatement: { VisitForEachVariableStatement((ForEachVariableStatementSyntax)node); break; } case SyntaxKind.ForStatement: { VisitForStatement((ForStatementSyntax)node); break; } case SyntaxKind.GotoStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoDefaultStatement: { VisitGotoStatement((GotoStatementSyntax)node); break; } case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: { VisitCheckedStatement((CheckedStatementSyntax)node); break; } case SyntaxKind.IfStatement: { VisitIfStatement((IfStatementSyntax)node); break; } case SyntaxKind.LabeledStatement: { VisitLabeledStatement((LabeledStatementSyntax)node); break; } case SyntaxKind.LocalDeclarationStatement: { VisitLocalDeclarationStatement((LocalDeclarationStatementSyntax)node); break; } case SyntaxKind.LocalFunctionStatement: { VisitLocalFunctionStatement((LocalFunctionStatementSyntax)node); break; } case SyntaxKind.LockStatement: { VisitLockStatement((LockStatementSyntax)node); break; } case SyntaxKind.ReturnStatement: { VisitReturnStatement((ReturnStatementSyntax)node); break; } case SyntaxKind.SwitchStatement: { VisitSwitchStatement((SwitchStatementSyntax)node); break; } case SyntaxKind.ThrowStatement: { VisitThrowStatement((ThrowStatementSyntax)node); break; } case SyntaxKind.TryStatement: { VisitTryStatement((TryStatementSyntax)node); break; } case SyntaxKind.UnsafeStatement: { VisitUnsafeStatement((UnsafeStatementSyntax)node); break; } case SyntaxKind.UsingStatement: { VisitUsingStatement((UsingStatementSyntax)node); break; } case SyntaxKind.WhileStatement: { VisitWhileStatement((WhileStatementSyntax)node); break; } case SyntaxKind.YieldBreakStatement: case SyntaxKind.YieldReturnStatement: { VisitYieldStatement((YieldStatementSyntax)node); break; } default: { SyntaxDebug.Fail(node); Visit(node); break; } } }
private static Func <CancellationToken, Task <Document> > GetCreateChangedDocument(CodeFixContext context, SyntaxNode node) { switch (node.Kind()) { case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; SyntaxToken semicolonToken = methodDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = methodDeclaration.ParameterList; if (parameterList == null) { break; } return(ct => { MethodDeclarationSyntax newNode = methodDeclaration .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.ConstructorDeclaration: { var constructorDeclaration = (ConstructorDeclarationSyntax)node; SyntaxToken semicolonToken = constructorDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = constructorDeclaration.ParameterList; if (parameterList == null) { break; } return(ct => { ConstructorDeclarationSyntax newNode = constructorDeclaration .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.DestructorDeclaration: { var destructorDeclaration = (DestructorDeclarationSyntax)node; SyntaxToken semicolonToken = destructorDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = destructorDeclaration.ParameterList; if (parameterList == null) { break; } return(ct => { DestructorDeclarationSyntax newNode = destructorDeclaration .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.OperatorDeclaration: { var operatorDeclaration = (OperatorDeclarationSyntax)node; SyntaxToken semicolonToken = operatorDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = operatorDeclaration.ParameterList; if (parameterList == null) { break; } return(ct => { OperatorDeclarationSyntax newNode = operatorDeclaration .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.ConversionOperatorDeclaration: { var conversionOperatorDeclaration = (ConversionOperatorDeclarationSyntax)node; SyntaxToken semicolonToken = conversionOperatorDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = conversionOperatorDeclaration.ParameterList; if (parameterList == null) { break; } return(ct => { ConversionOperatorDeclarationSyntax newNode = conversionOperatorDeclaration .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: { var accessorDeclaration = (AccessorDeclarationSyntax)node; SyntaxToken semicolonToken = accessorDeclaration.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } return(ct => { AccessorDeclarationSyntax newNode = accessorDeclaration .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block( Token(default(SyntaxTriviaList), SyntaxKind.OpenBraceToken, TriviaList(ElasticSpace)), default(SyntaxList <StatementSyntax>), Token(default(SyntaxTriviaList), SyntaxKind.CloseBraceToken, semicolonToken.LeadingAndTrailingTrivia()))); SyntaxToken keyword = newNode.Keyword; if (!keyword.HasTrailingTrivia) { newNode = newNode.WithKeyword(keyword.WithTrailingTrivia(ElasticSpace)); } return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } case SyntaxKind.LocalFunctionStatement: { var localFunction = (LocalFunctionStatementSyntax)node; SyntaxToken semicolonToken = localFunction.SemicolonToken; if (semicolonToken.IsKind(SyntaxKind.None)) { break; } ParameterListSyntax parameterList = localFunction.ParameterList; if (parameterList == null) { break; } return(ct => { LocalFunctionStatementSyntax newNode = localFunction .WithParameterList(parameterList.AppendToTrailingTrivia(semicolonToken.GetAllTrivia())) .WithSemicolonToken(default(SyntaxToken)) .WithBody(Block()) .WithFormatterAnnotation(); return context.Document.ReplaceNodeAsync(node, newNode, ct); }); } } SyntaxDebug.Fail(node); return(null); }
public static ImmutableArray <ISymbol> FindLocalSymbols( SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken = default) { var walker = new LocalSymbolCollector(semanticModel, cancellationToken); switch (node.Kind()) { case SyntaxKind.ConstructorDeclaration: { var constructor = (ConstructorDeclarationSyntax)node; walker.Visit(constructor.BodyOrExpressionBody()); break; } case SyntaxKind.EventDeclaration: { var eventDeclaration = (EventDeclarationSyntax)node; foreach (AccessorDeclarationSyntax accessor in eventDeclaration.AccessorList.Accessors) { walker.Visit(accessor.BodyOrExpressionBody()); } break; } case SyntaxKind.IndexerDeclaration: { var indexerDeclaration = (IndexerDeclarationSyntax)node; foreach (AccessorDeclarationSyntax accessor in indexerDeclaration.AccessorList.Accessors) { walker.Visit(accessor.BodyOrExpressionBody()); } break; } case SyntaxKind.MethodDeclaration: { var methodDeclaration = (MethodDeclarationSyntax)node; walker.Visit(methodDeclaration.BodyOrExpressionBody()); break; } case SyntaxKind.PropertyDeclaration: { var propertyDeclaration = (PropertyDeclarationSyntax)node; ArrowExpressionClauseSyntax expressionBody = propertyDeclaration.ExpressionBody; if (expressionBody != null) { walker.Visit(expressionBody); } else { foreach (AccessorDeclarationSyntax accessor in propertyDeclaration.AccessorList.Accessors) { walker.Visit(accessor.BodyOrExpressionBody()); } } break; } case SyntaxKind.VariableDeclarator: { var declarator = (VariableDeclaratorSyntax)node; ExpressionSyntax expression = declarator.Initializer?.Value; if (expression != null) { walker.Visit(expression); } break; } case SyntaxKind.OperatorDeclaration: { var declaration = (OperatorDeclarationSyntax)node; walker.Visit(declaration.BodyOrExpressionBody()); break; } case SyntaxKind.ConversionOperatorDeclaration: { var declaration = (ConversionOperatorDeclarationSyntax)node; walker.Visit(declaration.BodyOrExpressionBody()); break; } default: { SyntaxDebug.Fail(node); walker.Visit(node); break; } } return(walker.Definitions.ToImmutableArray()); }
private static void AnalyzeAccessorDeclarationBlock( SyntaxNodeAnalysisContext context, AccessorDeclarationSyntax accessor, BlockSyntax body) { if (body.ContainsDirectives) return; if (accessor.AttributeLists.Any()) return; BodyStyle style = context.GetBodyStyle(); if (style.IsDefault) return; bool isGetter = accessor.IsKind(SyntaxKind.GetAccessorDeclaration); BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(body, allowExpressionStatement: !isGetter); ExpressionSyntax expression = analysis.Expression; if (expression == null) return; if (!style.UseExpression) return; if (style.UseBlockWhenExpressionIsMultiLine == true && expression.IsMultiLine()) { return; } if (isGetter && accessor.Parent is AccessorListSyntax accessorList && accessorList.Accessors.Count == 1) { if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessorList.OpenBraceToken)) return; if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessor.Keyword)) return; if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken)) return; if (style.UseBlockWhenDeclarationIsMultiLine == true) { switch (accessorList.Parent.Kind()) { case SyntaxKind.PropertyDeclaration: { if (accessor.SyntaxTree.IsMultiLineSpan(((PropertyDeclarationSyntax)accessorList.Parent).HeaderSpan())) return; break; } case SyntaxKind.IndexerDeclaration: { if (accessor.SyntaxTree.IsMultiLineSpan(((IndexerDeclarationSyntax)accessorList.Parent).HeaderSpan())) return; break; } default: { SyntaxDebug.Fail(accessorList.Parent); break; } } return; } ReportDiagnostic(context, accessorList); return; } if (!accessor.Keyword.TrailingTrivia.IsEmptyOrWhitespace()) return; if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken)) return; if (!accessor.Keyword.LeadingTrivia.IsEmptyOrWhitespace()) return; ReportDiagnostic(context, body); }
public static void ComputeRefactoring(RefactoringContext context, SwitchStatementSyntax switchStatement) { SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; var containsNonDefaultSection = false; var containsSectionWithoutDefault = false; foreach (SwitchSectionSyntax section in sections) { var containsPattern = false; var containsDefault = false; foreach (SwitchLabelSyntax label in section.Labels) { switch (label.Kind()) { case SyntaxKind.CasePatternSwitchLabel: { containsPattern = true; break; } case SyntaxKind.CaseSwitchLabel: { break; } case SyntaxKind.DefaultSwitchLabel: { containsDefault = true; break; } default: { SyntaxDebug.Fail(label); return; } } if (containsDefault) { if (containsPattern) { return; } } else { containsSectionWithoutDefault = true; } } if (!containsDefault) { containsNonDefaultSection = true; } } if (!containsNonDefaultSection) { return; } if (!containsSectionWithoutDefault) { return; } context.RegisterRefactoring( "Convert to 'if'", ct => ConvertSwitchToIfAsync(context.Document, switchStatement, ct), RefactoringDescriptors.ConvertSwitchToIf); }
private static async Task <Document> RefactorAsync( Document document, StatementSyntax statement, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(statement); switch (statement) { case IfStatementSyntax ifStatement: { var expressionStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; ExpressionSyntax left = assignment.Left; ExpressionSyntax right = assignment.Right; BinaryExpressionSyntax coalesceExpression = CreateCoalesceExpression( left.WithoutLeadingTrivia().WithTrailingTrivia(Space), right.WithLeadingTrivia(Space), semanticModel.GetTypeSymbol(left, cancellationToken), semanticModel.GetTypeSymbol(right, cancellationToken)); AssignmentExpressionSyntax newAssignment = assignment.WithRight(coalesceExpression.WithTriviaFrom(right)); ExpressionStatementSyntax newNode = expressionStatement.WithExpression(newAssignment); IEnumerable <SyntaxTrivia> trivia = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, expressionStatement.SpanStart)); if (trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { newNode = newNode.WithLeadingTrivia(ifStatement.GetLeadingTrivia()); } else { newNode = newNode .WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(trivia)) .WithFormatterAnnotation(); } return(await document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken).ConfigureAwait(false)); } case ExpressionStatementSyntax expressionStatement: { var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; return(await RefactorAsync(document, expressionStatement, (IfStatementSyntax)statements[index + 1], index, statementsInfo, assignment.Right, semanticModel, cancellationToken).ConfigureAwait(false)); } case LocalDeclarationStatementSyntax localDeclaration: { ExpressionSyntax value = localDeclaration .Declaration .Variables[0] .Initializer .Value; return(await RefactorAsync(document, localDeclaration, (IfStatementSyntax)statements[index + 1], index, statementsInfo, value, semanticModel, cancellationToken).ConfigureAwait(false)); } default: { SyntaxDebug.Fail(statement); return(document); } } }
internal static bool IsFixable( IndexerDeclarationSyntax indexerDeclaration, AccessorDeclarationSyntax accessor, SemanticModel semanticModel, CancellationToken cancellationToken) { switch (accessor.Kind()) { case SyntaxKind.GetAccessorDeclaration: { ExpressionSyntax expression = GetGetAccessorExpression(accessor); if (expression is not ElementAccessExpressionSyntax elementAccess) { return(false); } if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (elementAccess.ArgumentList == null) { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) && CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) && CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters)); } case SyntaxKind.SetAccessorDeclaration: { ExpressionSyntax expression = GetSetAccessorExpression(accessor); SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!assignment.Success) { return(false); } if (assignment.Left.Kind() != SyntaxKind.ElementAccessExpression) { return(false); } var elementAccess = (ElementAccessExpressionSyntax)assignment.Left; if (elementAccess.Expression?.IsKind(SyntaxKind.BaseExpression) != true) { return(false); } if (elementAccess.ArgumentList == null) { return(false); } if (assignment.Right.Kind() != SyntaxKind.IdentifierName) { return(false); } var identifierName = (IdentifierNameSyntax)assignment.Right; if (identifierName.Identifier.ValueText != "value") { return(false); } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(indexerDeclaration, cancellationToken); if (propertySymbol == null) { return(false); } IPropertySymbol overriddenProperty = propertySymbol.OverriddenProperty; if (overriddenProperty == null) { return(false); } ISymbol symbol = semanticModel.GetSymbol(elementAccess, cancellationToken); return(SymbolEqualityComparer.Default.Equals(overriddenProperty, symbol) && CheckParameters(indexerDeclaration.ParameterList, elementAccess.ArgumentList, semanticModel, cancellationToken) && CheckDefaultValues(propertySymbol.Parameters, overriddenProperty.Parameters)); } case SyntaxKind.UnknownAccessorDeclaration: { return(false); } default: { SyntaxDebug.Fail(accessor); return(false); } } }
private static void AnalyzeParenthesizedExpression(SyntaxNodeAnalysisContext context) { var parenthesizedExpression = (ParenthesizedExpressionSyntax)context.Node; ExpressionSyntax expression = parenthesizedExpression.Expression; if (expression?.IsMissing != false) { return; } SyntaxToken openParen = parenthesizedExpression.OpenParenToken; if (openParen.IsMissing) { return; } SyntaxToken closeParen = parenthesizedExpression.CloseParenToken; if (closeParen.IsMissing) { return; } SyntaxNode parent = parenthesizedExpression.Parent; SyntaxKind parentKind = parent.Kind(); switch (parentKind) { case SyntaxKind.ParenthesizedExpression: case SyntaxKind.ArrowExpressionClause: case SyntaxKind.AttributeArgument: case SyntaxKind.Argument: case SyntaxKind.ExpressionStatement: case SyntaxKind.ReturnStatement: case SyntaxKind.YieldReturnStatement: case SyntaxKind.WhileStatement: case SyntaxKind.DoStatement: case SyntaxKind.UsingStatement: case SyntaxKind.LockStatement: case SyntaxKind.IfStatement: case SyntaxKind.SwitchStatement: case SyntaxKind.ArrayRankSpecifier: { ReportDiagnostic(); break; } case SyntaxKind.LessThanExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: { if (expression.IsKind(SyntaxKind.IdentifierName) || expression is LiteralExpressionSyntax) { ReportDiagnostic(); } break; } case SyntaxKind.MultiplyExpression: case SyntaxKind.DivideExpression: case SyntaxKind.ModuloExpression: case SyntaxKind.AddExpression: case SyntaxKind.SubtractExpression: case SyntaxKind.LeftShiftExpression: case SyntaxKind.RightShiftExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.LogicalAndExpression: case SyntaxKind.LogicalOrExpression: { SyntaxKind kind = expression.Kind(); if (kind == SyntaxKind.IdentifierName || expression is LiteralExpressionSyntax) { ReportDiagnostic(); } else if (kind == parentKind && ((BinaryExpressionSyntax)parent).Left == parenthesizedExpression) { ReportDiagnostic(); } break; } case SyntaxKind.LogicalNotExpression: { switch (expression.Kind()) { case SyntaxKind.IdentifierName: case SyntaxKind.GenericName: case SyntaxKind.InvocationExpression: case SyntaxKind.SimpleMemberAccessExpression: case SyntaxKind.ElementAccessExpression: case SyntaxKind.ConditionalAccessExpression: { ReportDiagnostic(); break; } } break; } case SyntaxKind.SimpleAssignmentExpression: case SyntaxKind.AddAssignmentExpression: case SyntaxKind.SubtractAssignmentExpression: case SyntaxKind.MultiplyAssignmentExpression: case SyntaxKind.DivideAssignmentExpression: case SyntaxKind.ModuloAssignmentExpression: case SyntaxKind.AndAssignmentExpression: case SyntaxKind.ExclusiveOrAssignmentExpression: case SyntaxKind.OrAssignmentExpression: case SyntaxKind.LeftShiftAssignmentExpression: case SyntaxKind.RightShiftAssignmentExpression: { if (((AssignmentExpressionSyntax)parent).Left == parenthesizedExpression) { ReportDiagnostic(); } else if (expression.IsKind(SyntaxKind.IdentifierName) || expression is LiteralExpressionSyntax) { ReportDiagnostic(); } break; } case SyntaxKind.Interpolation: { if (!expression.IsKind(SyntaxKind.ConditionalExpression) && !expression.DescendantNodes().Any(f => f.IsKind(SyntaxKind.AliasQualifiedName)) && ((InterpolationSyntax)parent).Expression == parenthesizedExpression) { ReportDiagnostic(); } break; } case SyntaxKind.AwaitExpression: { if (parenthesizedExpression.Expression.IsKind(SyntaxKind.SwitchExpression)) { return; } if (CSharpFacts.GetOperatorPrecedence(expression.Kind()) <= CSharpFacts.GetOperatorPrecedence(SyntaxKind.AwaitExpression)) { ReportDiagnostic(); } break; } case SyntaxKind.ArrayInitializerExpression: case SyntaxKind.CollectionInitializerExpression: { if (expression is not AssignmentExpressionSyntax) { ReportDiagnostic(); } break; } case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: { switch (parent.Parent.Kind()) { case SyntaxKind.ParenthesizedExpression: case SyntaxKind.ArrowExpressionClause: case SyntaxKind.Argument: case SyntaxKind.ReturnStatement: case SyntaxKind.YieldReturnStatement: case SyntaxKind.SimpleAssignmentExpression: case SyntaxKind.AddAssignmentExpression: case SyntaxKind.SubtractAssignmentExpression: { ReportDiagnostic(); break; } #if DEBUG default: { SyntaxDebug.Fail(parent.Parent); break; } #endif } break; } } void ReportDiagnostic() { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.RemoveRedundantParentheses, openParen.GetLocation(), additionalLocations: ImmutableArray.Create(closeParen.GetLocation())); DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, openParen); DiagnosticHelpers.ReportToken(context, DiagnosticRules.RemoveRedundantParenthesesFadeOut, closeParen); } }