public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { return SimplifyExpression( node, newNode: base.VisitParenthesizedExpression(node), simplifier: SimplifyParentheses); }
private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, ParenthesizedExpressionSyntax syntax) { var newSyntaxRoot = root.ReplaceNode(syntax, GetReplacement(syntax)); var changedDocument = document.WithSyntaxRoot(newSyntaxRoot); return Task.FromResult(changedDocument); }
private static SyntaxNode GetReplacement(ParenthesizedExpressionSyntax oldNode) { var leadingTrivia = SyntaxFactory.TriviaList(oldNode.OpenParenToken.GetAllTrivia().Concat(oldNode.Expression.GetLeadingTrivia())); var trailingTrivia = oldNode.Expression.GetTrailingTrivia().AddRange(oldNode.CloseParenToken.GetAllTrivia()); return oldNode.Expression .WithLeadingTrivia(leadingTrivia.Any() ? leadingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)) .WithTrailingTrivia(trailingTrivia.Any() ? trailingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)); }
public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { var newNode = base.VisitParenthesizedExpression(node); if (node != newNode && newNode.Kind() == SyntaxKind.ParenthesizedExpression) { return newNode.WithAdditionalAnnotations(Simplifier.Annotation); } return newNode; }
public override SyntaxNode VisitParenthesizedExpression (ParenthesizedExpressionSyntax node) { var newNode = base.VisitParenthesizedExpression (node); if (node != newNode && newNode.IsKind (SyntaxKind.ParenthesizedExpression)) { var parenthesizedExpression = (ParenthesizedExpressionSyntax)newNode; var innerExpression = parenthesizedExpression.OpenParenToken.GetNextToken ().Parent; if (innerExpression.HasAnnotation (_replacementAnnotation)) { return newNode.WithAdditionalAnnotations (Simplifier.Annotation); } } return newNode; }
private static Task<Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, ParenthesizedExpressionSyntax syntax) { var leadingTrivia = SyntaxFactory.TriviaList(syntax.OpenParenToken.GetAllTrivia().Concat(syntax.Expression.GetLeadingTrivia())); var trailingTrivia = syntax.Expression.GetTrailingTrivia().AddRange(syntax.CloseParenToken.GetAllTrivia()); var newNode = syntax.Expression .WithLeadingTrivia(leadingTrivia.Any() ? leadingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)) .WithTrailingTrivia(trailingTrivia.Any() ? trailingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)); var newSyntaxRoot = root.ReplaceNode(syntax, newNode); var changedDocument = document.WithSyntaxRoot(newSyntaxRoot); return Task.FromResult(changedDocument); }
private bool GetOuterMostParenthesizedExpressionInSpan(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken, out ParenthesizedExpressionSyntax result) { result = null; while (TryGetParenthesizedExpression(SignatureHelpTriggerReason.InvokeSignatureHelpCommand, root, position, syntaxFacts, cancellationToken, out var expression)) { if (!currentSpan.Contains(expression.Span)) { break; } result = expression; position = expression.SpanStart; } return result != null; }
private static SyntaxNode GetReplacement(ParenthesizedExpressionSyntax oldNode) { var leadingTrivia = SyntaxFactory.TriviaList(oldNode.OpenParenToken.GetAllTrivia().Concat(oldNode.Expression.GetLeadingTrivia())); var trailingTrivia = oldNode.Expression.GetTrailingTrivia().AddRange(oldNode.CloseParenToken.GetAllTrivia()); // Workaround for Roslyn not handling elastic markers for directive trivia correctly. if (!leadingTrivia.Any()) { var previousToken = oldNode.OpenParenToken.GetPreviousToken(); if (TriviaHelper.IndexOfTrailingWhitespace(previousToken.TrailingTrivia) == -1) { leadingTrivia = SyntaxFactory.TriviaList(SyntaxFactory.Space); } } return oldNode.Expression .WithLeadingTrivia(leadingTrivia) .WithTrailingTrivia(trailingTrivia.Any() ? trailingTrivia : SyntaxFactory.TriviaList(SyntaxFactory.ElasticMarker)); }
private static SyntaxNode SimplifyParentheses( ParenthesizedExpressionSyntax node, SemanticModel semanticModel, OptionSet optionSet, CancellationToken cancellationToken) { if (node.CanRemoveParentheses()) { // TODO(DustinCa): We should not be skipping elastic trivia below. // However, the formatter seems to mess up trailing trivia in some // cases if elastic trivia is there -- and it's not clear why. // Specifically remove the elastic trivia formatting rule doesn't // have any effect. var leadingTrivia = node.OpenParenToken.LeadingTrivia .Concat(node.OpenParenToken.TrailingTrivia) .Where(t => !t.IsElastic()) .Concat(node.Expression.GetLeadingTrivia()); var trailingTrivia = node.Expression.GetTrailingTrivia() .Concat(node.CloseParenToken.LeadingTrivia) .Where(t => !t.IsElastic()) .Concat(node.CloseParenToken.TrailingTrivia); var resultNode = node.Expression .WithLeadingTrivia(leadingTrivia) .WithTrailingTrivia(trailingTrivia); resultNode = SimplificationHelpers.CopyAnnotations(from: node, to: resultNode); return resultNode; } // We don't know how to simplifiy this. return node; }
public void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { if (node == null) throw new ArgumentNullException("node"); node.Validate(); ExpressionStart(node); _writer.WriteSyntax(Syntax.OpenParen); if (_writer.Configuration.Spaces.WithinParentheses.Parentheses) _writer.WriteSpace(); node.Expression.Accept(this); if (_writer.Configuration.Spaces.WithinParentheses.Parentheses) _writer.WriteSpace(); _writer.WriteSyntax(Syntax.CloseParen); ExpressionEnd(node); }
private static bool RemovalChangesAssociation(ParenthesizedExpressionSyntax node, ExpressionSyntax expression, ExpressionSyntax parentExpression) { var precedence = expression.GetOperatorPrecedence(); var parentPrecedence = parentExpression.GetOperatorPrecedence(); if (precedence == OperatorPrecedence.None || parentPrecedence == OperatorPrecedence.None) { // Be conservative if the expression or its parent has no precedence. return(true); } if (precedence > parentPrecedence) { // Association never changes if the expression's precedence is higher than its parent. return(false); } else if (precedence < parentPrecedence) { // Association always changes if the expression's precedence is lower that its parent. return(true); } else if (precedence == parentPrecedence) { // If the expression's precedence is the same as its parent, and both are binary expressions, // check for associativity and commutability. if (!(expression is BinaryExpressionSyntax || expression is AssignmentExpressionSyntax)) { // If the expression is not a binary expression, association never changes. return(false); } var parentBinaryExpression = parentExpression as BinaryExpressionSyntax; if (parentBinaryExpression != null) { // If both the expression and its parent are binary expressions and their kinds // are the same, check to see if they are commutative (e.g. + or *). if (parentBinaryExpression.IsKind(SyntaxKind.AddExpression, SyntaxKind.MultiplyExpression) && node.Expression.Kind() == parentBinaryExpression.Kind()) { return(false); } // Null-coalescing is right associative; removing parens from the LHS changes the association. if (parentExpression.IsKind(SyntaxKind.CoalesceExpression)) { return(parentBinaryExpression.Left == node); } // All other binary operators are left associative; removing parens from the RHS changes the association. return(parentBinaryExpression.Right == node); } var parentAssignmentExpression = parentExpression as AssignmentExpressionSyntax; if (parentAssignmentExpression != null) { // Assignment expressions are right associative; removing parens from the LHS changes the association. return(parentAssignmentExpression.Left == node); } // If the parent is not a binary expression, association never changes. return(false); } throw ExceptionUtilities.Unreachable; }
public override void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { emit("("); base.Visit(node.Expression); emit(")"); }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxKind kind = binaryExpression.Kind(); (ExpressionSyntax left, ExpressionSyntax right) = UseConditionalAccessAnalyzer.GetFixableExpressions(binaryExpression, kind, semanticModel, cancellationToken); NullCheckStyles allowedStyles = (kind == SyntaxKind.LogicalAndExpression) ? NullCheckStyles.NotEqualsToNull : NullCheckStyles.EqualsToNull; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, allowedStyles: allowedStyles); ExpressionSyntax expression = nullCheck.Expression; bool isNullable = semanticModel.GetTypeSymbol(expression, cancellationToken).IsNullableType(); ExpressionSyntax expression2 = UseConditionalAccessAnalyzer.FindExpressionThatCanBeConditionallyAccessed( expression, right, isNullable: isNullable, semanticModel, cancellationToken); var builder = new SyntaxNodeTextBuilder(binaryExpression, StringBuilderCache.GetInstance(binaryExpression.FullSpan.Length)); builder.Append(TextSpan.FromBounds(binaryExpression.FullSpan.Start, left.SpanStart)); int parenDiff = GetParenTokenDiff(); if (parenDiff > 0) { builder.Append('(', parenDiff); } builder.AppendSpan(expression); builder.Append("?"); builder.Append(TextSpan.FromBounds(expression2.Span.End, right.Span.End)); switch (right.Kind()) { case SyntaxKind.LogicalOrExpression: case SyntaxKind.LogicalAndExpression: case SyntaxKind.BitwiseOrExpression: case SyntaxKind.BitwiseAndExpression: case SyntaxKind.ExclusiveOrExpression: case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: case SyntaxKind.IsExpression: case SyntaxKind.AsExpression: case SyntaxKind.IsPatternExpression: { break; } case SyntaxKind.LogicalNotExpression: { builder.Append((kind == SyntaxKind.LogicalAndExpression) ? " == false" : " != true"); break; } default: { builder.Append((kind == SyntaxKind.LogicalAndExpression) ? " == true" : " != false"); break; } } if (parenDiff < 0) { builder.Append(')', -parenDiff); } builder.Append(TextSpan.FromBounds(right.Span.End, binaryExpression.FullSpan.End)); string text = StringBuilderCache.GetStringAndFree(builder.StringBuilder); ParenthesizedExpressionSyntax newNode = SyntaxFactory.ParseExpression(text) .WithFormatterAnnotation() .Parenthesize(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); int GetParenTokenDiff() { int count = 0; foreach (SyntaxToken token in binaryExpression.DescendantTokens(TextSpan.FromBounds(left.SpanStart, expression2.Span.End))) { SyntaxKind tokenKind = token.Kind(); if (tokenKind == SyntaxKind.OpenParenToken) { if (token.IsParentKind(SyntaxKind.ParenthesizedExpression)) { count++; } } else if (tokenKind == SyntaxKind.CloseParenToken) { if (token.IsParentKind(SyntaxKind.ParenthesizedExpression)) { count--; } } } return(count); } }
public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node) { var expression = node.Expression; var parentExpression = node.Parent as ExpressionSyntax; // Simplest cases: // ((x)) -> (x) if (expression.IsKind(SyntaxKind.ParenthesizedExpression) || parentExpression.IsKind(SyntaxKind.ParenthesizedExpression)) { return(true); } // Don't change (x?.Count).GetValueOrDefault() to x?.Count.GetValueOrDefault() if (expression.IsKind(SyntaxKind.ConditionalAccessExpression) && parentExpression is MemberAccessExpressionSyntax) { return(false); } // Easy statement-level cases: // var y = (x); -> var y = x; // if ((x)) -> if (x) // return (x); -> return x; // yield return (x); -> yield return x; // throw (x); -> throw x; // switch ((x)) -> switch (x) // while ((x)) -> while (x) // do { } while ((x)) -> do { } while (x) // for(;(x);) -> for(;x;) // foreach (var y in (x)) -> foreach (var y in x) // lock ((x)) -> lock (x) // using ((x)) -> using (x) // catch when ((x)) -> catch when (x) if ((node.IsParentKind(SyntaxKind.EqualsValueClause) && ((EqualsValueClauseSyntax)node.Parent).Value == node) || (node.IsParentKind(SyntaxKind.IfStatement) && ((IfStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ReturnStatement) && ((ReturnStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.YieldReturnStatement) && ((YieldStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.ThrowStatement) && ((ThrowStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.SwitchStatement) && ((SwitchStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.WhileStatement) && ((WhileStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.DoStatement) && ((DoStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForStatement) && ((ForStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForEachStatement) && ((ForEachStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.LockStatement) && ((LockStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.UsingStatement) && ((UsingStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.CatchFilterClause) && ((CatchFilterClauseSyntax)node.Parent).FilterExpression == node)) { return(true); } // Handle expression-level ambiguities if (RemovalMayIntroduceCastAmbiguity(node) || RemovalMayIntroduceCommaListAmbiguity(node) || RemovalMayIntroduceInterpolationAmbiguity(node)) { return(false); } // Cases: // y((x)) -> y(x) if (node.IsParentKind(SyntaxKind.Argument) && ((ArgumentSyntax)node.Parent).Expression == node) { return(true); } // Cases: // $"{(x)}" -> $"{x}" if (node.IsParentKind(SyntaxKind.Interpolation)) { return(true); } // Cases: // ($"{x}") -> $"{x}" if (expression.IsKind(SyntaxKind.InterpolatedStringExpression)) { return(true); } // Cases: // {(x)} -> {x} if (node.Parent is InitializerExpressionSyntax) { // Assignment expressions are not allowed in initializers if (expression.IsAnyAssignExpression()) { return(false); } return(true); } // Cases: // where (x + 1 > 14) -> where x + 1 > 14 if (node.Parent is QueryClauseSyntax) { return(true); } // Cases: // (x) -> x // (x.y) -> x.y if (IsSimpleOrDottedName(expression)) { return(true); } // Cases: // ('') -> '' // ("") -> "" // (false) -> false // (true) -> true // (null) -> null // (1) -> 1 if (expression.IsAnyLiteralExpression()) { return(true); } // Operator precedence cases: // - If the parent is not an expression, do not remove parentheses // - Otherwise, parentheses may be removed if doing so does not change operator associations. return(parentExpression != null ? !RemovalChangesAssociation(node, expression, parentExpression) : false); }
/// <summary> /// /// </summary> /// <param name="node"></param> public override sealed void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { this.OnNodeVisited(node); if (!this.traverseRootOnly) base.VisitParenthesizedExpression(node); }
public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { node = node.WithExpression((ExpressionSyntax)base.Visit((SyntaxNode)node.Expression)); switch (node.Expression.Kind) { case SyntaxKind.CharacterLiteralExpression: case SyntaxKind.FalseLiteralExpression: case SyntaxKind.NumericLiteralExpression: case SyntaxKind.StringLiteralExpression: case SyntaxKind.TrueLiteralExpression: return node.Expression; } return node; }
protected abstract void CompileParenthesizedExpression(ParenthesizedExpressionSyntax expression);
public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { _output.TrivialWrite('('); this.VisitExpression(node.Expression); _output.TrivialWrite(')'); return node; }
public override void VisitParenthesizedExpressionSyntax(ParenthesizedExpressionSyntax syntax) { this.AppendError(syntax); }
public override IExpression VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { return(this.Visit(node.Expression)); }
public static void Go(OutputWriter writer, ParenthesizedExpressionSyntax expression) { writer.Write("("); Core.Write(writer, expression.Expression); writer.Write(")"); }
private static bool RemovalChangesAssociation(ParenthesizedExpressionSyntax node, ExpressionSyntax expression, ExpressionSyntax parentExpression, SemanticModel semanticModel) { var precedence = expression.GetOperatorPrecedence(); var parentPrecedence = parentExpression.GetOperatorPrecedence(); if (precedence == OperatorPrecedence.None || parentPrecedence == OperatorPrecedence.None) { // Be conservative if the expression or its parent has no precedence. return(true); } if (precedence > parentPrecedence) { // Association never changes if the expression's precedence is higher than its parent. return(false); } else if (precedence < parentPrecedence) { // Association always changes if the expression's precedence is lower that its parent. return(true); } else if (precedence == parentPrecedence) { // If the expression's precedence is the same as its parent, and both are binary expressions, // check for associativity and commutability. if (!(expression is BinaryExpressionSyntax || expression is AssignmentExpressionSyntax)) { // If the expression is not a binary expression, association never changes. return(false); } if (parentExpression is BinaryExpressionSyntax parentBinaryExpression) { // If both the expression and its parent are binary expressions and their kinds // are the same, check to see if they are commutative (e.g. + or *). if (parentBinaryExpression.IsKind(SyntaxKind.AddExpression, SyntaxKind.MultiplyExpression) && node.Expression.Kind() == parentBinaryExpression.Kind()) { // At this point, we know our parenthesized expression contains a binary expression. var binaryExpression = (BinaryExpressionSyntax)node.Expression; // Now we'll perform a few semantic checks to determine whether removal of the parentheses // might break semantics. Note that we'll try and be fairly conservative with these. For example, // we'll assume that failing any of these checks results in the parentheses being declared as // necessary -- even if they could be removed depending on whether the parenthesized expression // appears on the left or right side of the parent binary expression. // First, does the binary expression result in an operator overload being called? var symbolInfo = semanticModel.GetSymbolInfo(binaryExpression); if (symbolInfo.Symbol != null) { if (symbolInfo.Symbol is IMethodSymbol methodSymbol && methodSymbol.MethodKind == MethodKind.UserDefinedOperator) { return(true); } } // Second, check the type and converted type of the binary expression. Are they the same? var typeInfo = semanticModel.GetTypeInfo(binaryExpression); if (typeInfo.Type != null && typeInfo.ConvertedType != null) { if (!typeInfo.Type.Equals(typeInfo.ConvertedType)) { return(true); } } return(false); } // Null-coalescing is right associative; removing parens from the LHS changes the association. if (parentExpression.IsKind(SyntaxKind.CoalesceExpression)) { return(parentBinaryExpression.Left == node); } // All other binary operators are left associative; removing parens from the RHS changes the association. return(parentBinaryExpression.Right == node); } if (parentExpression is AssignmentExpressionSyntax parentAssignmentExpression) { // Assignment expressions are right associative; removing parens from the LHS changes the association. return(parentAssignmentExpression.Left == node); } // If the parent is not a binary expression, association never changes. return(false); } throw ExceptionUtilities.Unreachable; }
public override void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { node.Expression.Accept(this); }
public override void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { base.VisitParenthesizedExpression(node); }
public virtual void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) => DefaultVisit(node);
private bool TryGetParenthesizedExpression(SignatureHelpTriggerReason triggerReason, SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken, out ParenthesizedExpressionSyntax parenthesizedExpression) { return CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsParenthesizedExpressionTriggerToken, IsParenthesizedExpressionToken, cancellationToken, out parenthesizedExpression); }
private static bool RemovalMayIntroduceCommaListAmbiguity(ParenthesizedExpressionSyntax node) { if (IsSimpleOrDottedName(node.Expression)) { // We can't remove parentheses from an identifier name in the following cases: // F((x) < x, x > (1 + 2)) // F(x < (x), x > (1 + 2)) // F(x < x, (x) > (1 + 2)) // {(x) < x, x > (1 + 2)} // {x < (x), x > (1 + 2)} // {x < x, (x) > (1 + 2)} var binaryExpression = node.Parent as BinaryExpressionSyntax; if (binaryExpression != null && binaryExpression.MatchesKind(SyntaxKind.LessThanExpression, SyntaxKind.GreaterThanExpression) && (binaryExpression.IsParentKind(SyntaxKind.Argument) || binaryExpression.Parent is InitializerExpressionSyntax)) { if (binaryExpression.IsKind(SyntaxKind.LessThanExpression)) { if ((binaryExpression.Left == node && IsSimpleOrDottedName(binaryExpression.Right)) || (binaryExpression.Right == node && IsSimpleOrDottedName(binaryExpression.Left))) { if (IsNextExpressionPotentiallyAmbiguous(binaryExpression)) { return true; } } return false; } else if (binaryExpression.IsKind(SyntaxKind.GreaterThanExpression)) { if (binaryExpression.Left == node && binaryExpression.Right.MatchesKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.CastExpression)) { if (IsPreviousExpressionPotentiallyAmbiguous(binaryExpression)) { return true; } } return false; } } } else if (node.Expression.MatchesKind(SyntaxKind.LessThanExpression)) { // We can't remove parentheses from a less-than expression in the following cases: // F((x < x), x > (1 + 2)) // {(x < x), x > (1 + 2)} var lessThanExpression = (BinaryExpressionSyntax)node.Expression; if (IsNextExpressionPotentiallyAmbiguous(node)) { return true; } return false; } else if (node.Expression.MatchesKind(SyntaxKind.GreaterThanExpression)) { // We can't remove parentheses from a greater-than expression in the following cases: // F(x < x, (x > (1 + 2))) // {x < x, (x > (1 + 2))} var greaterThanExpression = (BinaryExpressionSyntax)node.Expression; if (IsPreviousExpressionPotentiallyAmbiguous(node)) { return true; } return false; } return false; }
public override string VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { return(node.OpenParenToken + Visit(node.Expression) + node.CloseParenToken); }
/// <inheritdoc /> public override Expression VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { return(node.Expression.Accept(this)); }
public void Render(ParenthesizedExpressionSyntax parenthesizedExpression) { Render(parenthesizedExpression.OpenParenthesisSymbol); Render(parenthesizedExpression.ExpressionNode); Render(parenthesizedExpression.CloseParenthesisSymbol); }
private static bool RemovalMayIntroduceInterpolationAmbiguity(ParenthesizedExpressionSyntax node) { // First, find the parenting interpolation. If we find a parenthesize expression first, // we can bail out early. InterpolationSyntax interpolation = null; foreach (var ancestor in node.Parent.AncestorsAndSelf()) { switch (ancestor.Kind()) { case SyntaxKind.ParenthesizedExpression: return false; case SyntaxKind.Interpolation: interpolation = (InterpolationSyntax)ancestor; break; } } if (interpolation == null) { return false; } // In order determine whether removing this parenthesized expression will introduce a // parsing ambiguity, we must dig into the child tokens and nodes to determine whether // they include any : or :: tokens. If they do, we can't remove the parentheses because // the parser would assume that the first : would begin the format clause of the interpolation. var stack = s_nodeStackPool.AllocateAndClear(); try { stack.Push(node.Expression); while (stack.Count > 0) { var expression = stack.Pop(); foreach (var nodeOrToken in expression.ChildNodesAndTokens()) { // Note: There's no need drill into other parenthesized expressions, since any colons in them would be unambiguous. if (nodeOrToken.IsNode && !nodeOrToken.IsKind(SyntaxKind.ParenthesizedExpression)) { stack.Push(nodeOrToken.AsNode()); } else if (nodeOrToken.IsToken) { if (nodeOrToken.IsKind(SyntaxKind.ColonToken) || nodeOrToken.IsKind(SyntaxKind.ColonColonToken)) { return true; } } } } } finally { s_nodeStackPool.ClearAndFree(stack); } return false; }
public override void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) => node.Expression.Accept(this);
private static bool RemovalChangesAssociation(ParenthesizedExpressionSyntax node, ExpressionSyntax expression, ExpressionSyntax parentExpression) { var precedence = expression.GetOperatorPrecedence(); var parentPrecedence = parentExpression.GetOperatorPrecedence(); if (precedence == OperatorPrecedence.None || parentPrecedence == OperatorPrecedence.None) { // Be conservative if the expression or its parent has no precedence. return true; } if (precedence > parentPrecedence) { // Association never changes if the expression's precedence is higher than its parent. return false; } else if (precedence < parentPrecedence) { // Association always changes if the expression's precedence is lower that its parent. return true; } else if (precedence == parentPrecedence) { // If the expression's precedence is the same as its parent, and both are binary expressions, // check for associativity and commutability. if (!(expression is BinaryExpressionSyntax || expression is AssignmentExpressionSyntax)) { // If the expression is not a binary expression, association never changes. return false; } var parentBinaryExpression = parentExpression as BinaryExpressionSyntax; if (parentBinaryExpression != null) { // If both the expression and its parent are binary expressions and their kinds // are the same, check to see if they are commutative (e.g. + or *). if (parentBinaryExpression.IsKind(SyntaxKind.AddExpression, SyntaxKind.MultiplyExpression) && node.Expression.Kind() == parentBinaryExpression.Kind()) { return false; } // Null-coalescing is right associative; removing parens from the LHS changes the association. if (parentExpression.IsKind(SyntaxKind.CoalesceExpression)) { return parentBinaryExpression.Left == node; } // All other binary operators are left associative; removing parens from the RHS changes the association. return parentBinaryExpression.Right == node; } var parentAssignmentExpression = parentExpression as AssignmentExpressionSyntax; if (parentAssignmentExpression != null) { // Assignment expressions are right associative; removing parens from the LHS changes the association. return parentAssignmentExpression.Left == node; } // If the parent is not a binary expression, association never changes. return false; } throw ExceptionUtilities.Unreachable; }
private static bool RemovalMayIntroduceCastAmbiguity(ParenthesizedExpressionSyntax node) { // Be careful not to break the special case around (x)(-y) // as defined in section 7.7.6 of the C# language specification. if (node.IsParentKind(SyntaxKind.CastExpression)) { var castExpression = (CastExpressionSyntax)node.Parent; if (castExpression.Type is PredefinedTypeSyntax) { return false; } var expression = node.Expression; if (expression.IsKind(SyntaxKind.UnaryMinusExpression)) { return true; } if (expression.IsKind(SyntaxKind.NumericLiteralExpression)) { var numericLiteral = (LiteralExpressionSyntax)expression; if (numericLiteral.Token.ValueText.StartsWith("-")) { return true; } } } return false; }
public ParenthesizedExpressionTranslation(ParenthesizedExpressionSyntax syntax, SyntaxTranslation parent) : base(syntax, parent) { Expression = syntax.Expression.Get <ExpressionTranslation>(this); }
public override Evaluation VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { node.Expression?.Accept <Evaluation>(this); return(base.VisitParenthesizedExpression(node)); }
private static Task <Document> GetTransformedDocumentAsync(Document document, SyntaxNode root, ParenthesizedExpressionSyntax syntax) { var newSyntaxRoot = root.ReplaceNode(syntax, GetReplacement(syntax)); var changedDocument = document.WithSyntaxRoot(newSyntaxRoot); return(Task.FromResult(changedDocument)); }
private bool TryGetParenthesizedExpression(SignatureHelpTriggerReason triggerReason, SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, CancellationToken cancellationToken, out ParenthesizedExpressionSyntax parenthesizedExpression) { return(CommonSignatureHelpUtilities.TryGetSyntax(root, position, syntaxFacts, triggerReason, IsParenthesizedExpressionTriggerToken, IsParenthesizedExpressionToken, cancellationToken, out parenthesizedExpression)); }
private static bool RemovalMayIntroduceInterpolationAmbiguity(ParenthesizedExpressionSyntax node) { // First, find the parenting interpolation. If we find a parenthesize expression first, // we can bail out early. InterpolationSyntax interpolation = null; foreach (var ancestor in node.Parent.AncestorsAndSelf()) { switch (ancestor.Kind()) { case SyntaxKind.ParenthesizedExpression: return(false); case SyntaxKind.Interpolation: interpolation = (InterpolationSyntax)ancestor; break; } } if (interpolation == null) { return(false); } // In order determine whether removing this parenthesized expression will introduce a // parsing ambiguity, we must dig into the child tokens and nodes to determine whether // they include any : or :: tokens. If they do, we can't remove the parentheses because // the parser would assume that the first : would begin the format clause of the interpolation. var stack = s_nodeStackPool.AllocateAndClear(); try { stack.Push(node.Expression); while (stack.Count > 0) { var expression = stack.Pop(); foreach (var nodeOrToken in expression.ChildNodesAndTokens()) { // Note: There's no need drill into other parenthesized expressions, since any colons in them would be unambiguous. if (nodeOrToken.IsNode && !nodeOrToken.IsKind(SyntaxKind.ParenthesizedExpression)) { stack.Push(nodeOrToken.AsNode()); } else if (nodeOrToken.IsToken) { if (nodeOrToken.IsKind(SyntaxKind.ColonToken) || nodeOrToken.IsKind(SyntaxKind.ColonColonToken)) { return(true); } } } } } finally { s_nodeStackPool.ClearAndFree(stack); } return(false); }
private bool GetOuterMostParenthesizedExpressionInSpan(SyntaxNode root, int position, ISyntaxFactsService syntaxFacts, TextSpan currentSpan, CancellationToken cancellationToken, out ParenthesizedExpressionSyntax result) { result = null; while (TryGetParenthesizedExpression(SignatureHelpTriggerReason.InvokeSignatureHelpCommand, root, position, syntaxFacts, cancellationToken, out var expression)) { if (!currentSpan.Contains(expression.Span)) { break; } result = expression; position = expression.SpanStart; } return(result != null); }
private static bool RemovalMayIntroduceCommaListAmbiguity(ParenthesizedExpressionSyntax node) { if (IsSimpleOrDottedName(node.Expression)) { // We can't remove parentheses from an identifier name in the following cases: // F((x) < x, x > (1 + 2)) // F(x < (x), x > (1 + 2)) // F(x < x, (x) > (1 + 2)) // {(x) < x, x > (1 + 2)} // {x < (x), x > (1 + 2)} // {x < x, (x) > (1 + 2)} var binaryExpression = node.Parent as BinaryExpressionSyntax; if (binaryExpression != null && binaryExpression.IsKind(SyntaxKind.LessThanExpression, SyntaxKind.GreaterThanExpression) && (binaryExpression.IsParentKind(SyntaxKind.Argument) || binaryExpression.Parent is InitializerExpressionSyntax)) { if (binaryExpression.IsKind(SyntaxKind.LessThanExpression)) { if ((binaryExpression.Left == node && IsSimpleOrDottedName(binaryExpression.Right)) || (binaryExpression.Right == node && IsSimpleOrDottedName(binaryExpression.Left))) { if (IsNextExpressionPotentiallyAmbiguous(binaryExpression)) { return(true); } } return(false); } else if (binaryExpression.IsKind(SyntaxKind.GreaterThanExpression)) { if (binaryExpression.Left == node && binaryExpression.Right.IsKind(SyntaxKind.ParenthesizedExpression, SyntaxKind.CastExpression)) { if (IsPreviousExpressionPotentiallyAmbiguous(binaryExpression)) { return(true); } } return(false); } } } else if (node.Expression.IsKind(SyntaxKind.LessThanExpression)) { // We can't remove parentheses from a less-than expression in the following cases: // F((x < x), x > (1 + 2)) // {(x < x), x > (1 + 2)} var lessThanExpression = (BinaryExpressionSyntax)node.Expression; if (IsNextExpressionPotentiallyAmbiguous(node)) { return(true); } return(false); } else if (node.Expression.IsKind(SyntaxKind.GreaterThanExpression)) { // We can't remove parentheses from a greater-than expression in the following cases: // F(x < x, (x > (1 + 2))) // {x < x, (x > (1 + 2))} var greaterThanExpression = (BinaryExpressionSyntax)node.Expression; if (IsPreviousExpressionPotentiallyAmbiguous(node)) { return(true); } return(false); } return(false); }
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntax expressionSyntax) { return(BindExpression(expressionSyntax.Expression)); }
public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node) { var expression = node.Expression; var parentExpression = node.Parent as ExpressionSyntax; // Simplest cases: // ((x)) -> (x) if (expression.IsKind(SyntaxKind.ParenthesizedExpression)) { return(true); } // Easy statement-level cases: // var y = (x); -> var y = x; // if ((x)) -> if (x) // return (x); -> return x; // yield return (x); -> yield return x; // throw (x); -> throw x; // switch ((x)) -> switch (x) // while ((x)) -> while (x) // do { } while ((x)) -> do { } while (x) // for(;(x);) -> for(;x;) // foreach (var y in (x)) -> foreach (var y in x) // lock ((x)) -> lock (x) // using ((x)) -> using (x) if ((node.IsParentKind(SyntaxKind.EqualsValueClause) && ((EqualsValueClauseSyntax)node.Parent).Value == node) || (node.IsParentKind(SyntaxKind.IfStatement) && ((IfStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ReturnStatement) && ((ReturnStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.YieldReturnStatement) && ((YieldStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.ThrowStatement) && ((ThrowStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.SwitchStatement) && ((SwitchStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.WhileStatement) && ((WhileStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.DoStatement) && ((DoStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForStatement) && ((ForStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForEachStatement) && ((ForEachStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.LockStatement) && ((LockStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.UsingStatement) && ((UsingStatementSyntax)node.Parent).Expression == node)) { return(true); } // Handle expression-level ambiguities if (RemovalMayIntroduceCastAmbiguity(node) || RemovalMayIntroduceCommaListAmbiguity(node)) { return(false); } // Cases: // y((x)) -> y(x) if (node.IsParentKind(SyntaxKind.Argument) && ((ArgumentSyntax)node.Parent).Expression == node) { return(true); } // Cases: // {(x)} -> {x} if (node.Parent is InitializerExpressionSyntax) { // Assignment expressions are not allowed in initializers if (expression.IsAnyAssignExpression()) { return(false); } return(true); } // Cases: // where (x + 1 > 14) -> where x + 1 > 14 if (node.Parent is QueryClauseSyntax) { return(true); } // Cases: // (x) -> x // (x.y) -> x.y if (IsSimpleOrDottedName(expression)) { return(true); } // Cases: // ('') -> '' // ("") -> "" // (false) -> false // (true) -> true // (null) -> null // (1) -> 1 if (expression.IsAnyLiteralExpression()) { return(true); } // Operator precedence cases: var precedence = expression.GetOperatorPrecedence(); if (parentExpression != null) { var parentPrecedence = parentExpression.GetOperatorPrecedence(); // Only remove if the expression's precedence is higher than its parent. if (parentPrecedence != OperatorPrecedence.None && precedence > parentPrecedence) { return(true); } // If the expression's precedence is the same as its parent, and both are binary expressions, // check for associativity and commutability. if (precedence != OperatorPrecedence.None && precedence == parentPrecedence) { var binaryExpression = expression as BinaryExpressionSyntax; var parentBinaryExpression = parentExpression as BinaryExpressionSyntax; if (binaryExpression == null || parentBinaryExpression == null) { return(true); } // Handle associate cases. Note that all binary expressions except assignment // and null-coalescing are left associative. if (parentBinaryExpression.Left == node) { if (!parentBinaryExpression.IsAnyAssignExpression() && !parentBinaryExpression.IsKind(SyntaxKind.CoalesceExpression)) { return(true); } } else if (parentBinaryExpression.Right == node) { if (parentBinaryExpression.IsAnyAssignExpression() || parentBinaryExpression.IsKind(SyntaxKind.CoalesceExpression)) { return(true); } } // If both the expression and it's parent are binary expressions and their kinds // are the same, check to see if they are commutative (e.g. + or *). if (parentBinaryExpression.MatchesKind(SyntaxKind.AddExpression, SyntaxKind.MultiplyExpression) && expression.CSharpKind() == parentExpression.CSharpKind()) { return(true); } } } return(false); }
/// <summary> /// /// </summary> /// <param name="node"></param> public override sealed void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { this.OnNodeVisited(node, this.type.IsInstanceOfType(node)); base.VisitParenthesizedExpression(node); }
private static bool IsParenthesizedExpressionToken(ParenthesizedExpressionSyntax expr, SyntaxToken token) { return(expr.FullSpan.Contains(token.SpanStart) && token != expr.CloseParenToken); }
private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, ParenthesizedExpressionSyntax node) { context.ReportDiagnostic(Diagnostic.Create(Descriptor, node.GetLocation())); context.ReportDiagnostic(Diagnostic.Create(ParenthesisDescriptor, node.OpenParenToken.GetLocation())); context.ReportDiagnostic(Diagnostic.Create(ParenthesisDescriptor, node.CloseParenToken.GetLocation())); }
public override BoundNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { return(VisitExpression(node.Expression)); }
public static bool CanRemoveParentheses(this ParenthesizedExpressionSyntax node, SemanticModel semanticModel) { var expression = node.Expression; // The 'direct' expression that contains this parenthesized node. Note: in the case // of code like: ```x is (y)``` there is an intermediary 'no-syntax' 'ConstantPattern' // node between the 'is-pattern' node and the parenthesized expression. So we manually // jump past that as, for all intents and purposes, we want to consider the 'is' expression // as the parent expression of the (y) expression. var parentExpression = node.IsParentKind(SyntaxKind.ConstantPattern) ? node.Parent.Parent as ExpressionSyntax : node.Parent as ExpressionSyntax; // Simplest cases: // ((x)) -> (x) if (expression.IsKind(SyntaxKind.ParenthesizedExpression) || parentExpression.IsKind(SyntaxKind.ParenthesizedExpression)) { return(true); } // (x); -> x; if (node.IsParentKind(SyntaxKind.ExpressionStatement)) { return(true); } // => (x) -> => x if (node.IsParentKind(SyntaxKind.ArrowExpressionClause)) { return(true); } // checked((x)) -> checked(x) if (node.IsParentKind(SyntaxKind.CheckedExpression) || node.IsParentKind(SyntaxKind.UncheckedExpression)) { return(true); } // ((x, y)) -> (x, y) if (expression.IsKind(SyntaxKind.TupleExpression)) { return(true); } // int Prop => (x); -> int Prop => x; if (node.Parent is ArrowExpressionClauseSyntax arrowExpressionClause && arrowExpressionClause.Expression == node) { return(true); } // Don't change (x?.Count).GetValueOrDefault() to x?.Count.GetValueOrDefault() if (expression.IsKind(SyntaxKind.ConditionalAccessExpression) && parentExpression is MemberAccessExpressionSyntax) { return(false); } // Easy statement-level cases: // var y = (x); -> var y = x; // var (y, z) = (x); -> var (y, z) = x; // if ((x)) -> if (x) // return (x); -> return x; // yield return (x); -> yield return x; // throw (x); -> throw x; // switch ((x)) -> switch (x) // while ((x)) -> while (x) // do { } while ((x)) -> do { } while (x) // for(;(x);) -> for(;x;) // foreach (var y in (x)) -> foreach (var y in x) // lock ((x)) -> lock (x) // using ((x)) -> using (x) // catch when ((x)) -> catch when (x) if ((node.IsParentKind(SyntaxKind.EqualsValueClause) && ((EqualsValueClauseSyntax)node.Parent).Value == node) || (node.IsParentKind(SyntaxKind.IfStatement) && ((IfStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ReturnStatement) && ((ReturnStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.YieldReturnStatement) && ((YieldStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.ThrowStatement) && ((ThrowStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.SwitchStatement) && ((SwitchStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.WhileStatement) && ((WhileStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.DoStatement) && ((DoStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForStatement) && ((ForStatementSyntax)node.Parent).Condition == node) || (node.IsParentKind(SyntaxKind.ForEachStatement, SyntaxKind.ForEachVariableStatement) && ((CommonForEachStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.LockStatement) && ((LockStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.UsingStatement) && ((UsingStatementSyntax)node.Parent).Expression == node) || (node.IsParentKind(SyntaxKind.CatchFilterClause) && ((CatchFilterClauseSyntax)node.Parent).FilterExpression == node)) { return(true); } // Handle expression-level ambiguities if (RemovalMayIntroduceCastAmbiguity(node) || RemovalMayIntroduceCommaListAmbiguity(node) || RemovalMayIntroduceInterpolationAmbiguity(node)) { return(false); } // Cases: // (C)(this) -> (C)this if (node.IsParentKind(SyntaxKind.CastExpression) && expression.IsKind(SyntaxKind.ThisExpression)) { return(true); } // Cases: // y((x)) -> y(x) if (node.IsParentKind(SyntaxKind.Argument) && ((ArgumentSyntax)node.Parent).Expression == node) { return(true); } // Cases: // $"{(x)}" -> $"{x}" if (node.IsParentKind(SyntaxKind.Interpolation)) { return(true); } // Cases: // ($"{x}") -> $"{x}" if (expression.IsKind(SyntaxKind.InterpolatedStringExpression)) { return(true); } // Cases: // {(x)} -> {x} if (node.Parent is InitializerExpressionSyntax) { // Assignment expressions are not allowed in initializers if (expression.IsAnyAssignExpression()) { return(false); } return(true); } // Cases: // new {(x)} -> {x} // new { a = (x)} -> { a = x } // new { a = (x = c)} -> { a = x = c } if (node.Parent is AnonymousObjectMemberDeclaratorSyntax anonymousDeclarator) { // Assignment expressions are not allowed unless member is named if (anonymousDeclarator.NameEquals == null && expression.IsAnyAssignExpression()) { return(false); } return(true); } // Cases: // where (x + 1 > 14) -> where x + 1 > 14 if (node.Parent is QueryClauseSyntax) { return(true); } // Cases: // (x) -> x // (x.y) -> x.y if (IsSimpleOrDottedName(expression)) { return(true); } // Cases: // ('') -> '' // ("") -> "" // (false) -> false // (true) -> true // (null) -> null // (1) -> 1 if (expression.IsAnyLiteralExpression()) { return(true); } // x ?? (throw ...) -> x ?? throw ... if (expression.IsKind(SyntaxKind.ThrowExpression) && node.IsParentKind(SyntaxKind.CoalesceExpression) && ((BinaryExpressionSyntax)node.Parent).Right == node) { return(true); } // case (x): -> case x: if (node.IsParentKind(SyntaxKind.CaseSwitchLabel)) { return(true); } // case (x) when y: -> case x when y: if (node.IsParentKind(SyntaxKind.ConstantPattern) && node.Parent.IsParentKind(SyntaxKind.CasePatternSwitchLabel)) { return(true); } // case x when (y): -> case x when y: if (node.IsParentKind(SyntaxKind.WhenClause)) { return(true); } // Operator precedence cases: // - If the parent is not an expression, do not remove parentheses // - Otherwise, parentheses may be removed if doing so does not change operator associations. return(parentExpression != null && !RemovalChangesAssociation(node, parentExpression, semanticModel)); }
public override void VisitParenthesizedExpressionSyntax(ParenthesizedExpressionSyntax syntax) => this.BuildWithConcat(() => base.VisitParenthesizedExpressionSyntax(syntax));
private static bool RemovalChangesAssociation( ParenthesizedExpressionSyntax node, ExpressionSyntax parentExpression, SemanticModel semanticModel) { var expression = node.Expression; var precedence = expression.GetOperatorPrecedence(); var parentPrecedence = parentExpression.GetOperatorPrecedence(); if (precedence == OperatorPrecedence.None || parentPrecedence == OperatorPrecedence.None) { // Be conservative if the expression or its parent has no precedence. return(true); } if (precedence > parentPrecedence) { // Association never changes if the expression's precedence is higher than its parent. return(false); } else if (precedence < parentPrecedence) { // Association always changes if the expression's precedence is lower that its parent. return(true); } else if (precedence == parentPrecedence) { // If the expression's precedence is the same as its parent, and both are binary expressions, // check for associativity and commutability. if (!(expression is BinaryExpressionSyntax || expression is AssignmentExpressionSyntax)) { // If the expression is not a binary expression, association never changes. return(false); } if (parentExpression is BinaryExpressionSyntax parentBinaryExpression) { // If both the expression and its parent are binary expressions and their kinds // are the same, and the parenthesized expression is on hte right and the // operation is associative, it can sometimes be safe to remove these parens. // // i.e. if you have "a && (b && c)" it can be converted to "a && b && c" // as that new interpretation "(a && b) && c" operates the exact same way at // runtime. // // Specifically: // 1) the operands are still executed in the same order: a, b, then c. // So even if they have side effects, it will not matter. // 2) the same shortcircuiting happens. // 3) for logical operators the result will always be the same (there are // additional conditions that are checked for non-logical operators). if (IsAssociative(parentBinaryExpression.Kind()) && node.Expression.Kind() == parentBinaryExpression.Kind() && parentBinaryExpression.Right == node) { return(!node.IsSafeToChangeAssociativity( node.Expression, parentBinaryExpression.Left, parentBinaryExpression.Right, semanticModel)); } // Null-coalescing is right associative; removing parens from the LHS changes the association. if (parentExpression.IsKind(SyntaxKind.CoalesceExpression)) { return(parentBinaryExpression.Left == node); } // All other binary operators are left associative; removing parens from the RHS changes the association. return(parentBinaryExpression.Right == node); } if (parentExpression is AssignmentExpressionSyntax parentAssignmentExpression) { // Assignment expressions are right associative; removing parens from the LHS changes the association. return(parentAssignmentExpression.Left == node); } // If the parent is not a binary expression, association never changes. return(false); } throw ExceptionUtilities.Unreachable; }
private bool TryGenerateParentheses(ParenthesizedExpressionSyntax parenthesizedExpression) { using (ParenthesesTag()) { return TryGenerateExpression(parenthesizedExpression.Expression); } }
private static bool IsParenthesizedExpressionToken(ParenthesizedExpressionSyntax expr, SyntaxToken token) { return expr.FullSpan.Contains(token.SpanStart) && token != expr.CloseParenToken; }
public override void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { throw new NotImplementedException(); }
public static Task <Document> RefactorAsync( Document document, ParenthesizedExpressionSyntax parenthesizedExpression, CancellationToken cancellationToken = default(CancellationToken)) { ExpressionSyntax expression = parenthesizedExpression.Expression; SyntaxTriviaList leading = parenthesizedExpression.GetLeadingTrivia() .Concat(parenthesizedExpression.OpenParenToken.TrailingTrivia) .Concat(expression.GetLeadingTrivia()) .ToSyntaxTriviaList(); SyntaxTriviaList trailing = expression.GetTrailingTrivia() .Concat(parenthesizedExpression.CloseParenToken.LeadingTrivia) .Concat(parenthesizedExpression.GetTrailingTrivia()) .ToSyntaxTriviaList(); ExpressionSyntax newExpression = expression .WithLeadingTrivia(leading) .WithTrailingTrivia(trailing) .WithFormatterAnnotation(); if (!leading.Any()) { SyntaxNode parent = parenthesizedExpression.Parent; switch (parent.Kind()) { case SyntaxKind.ReturnStatement: { var returnStatement = (ReturnStatementSyntax)parent; SyntaxToken returnKeyword = returnStatement.ReturnKeyword; if (!returnKeyword.TrailingTrivia.Any()) { ReturnStatementSyntax newNode = returnStatement.Update(returnKeyword.WithTrailingTrivia(Space), newExpression, returnStatement.SemicolonToken); return(document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken)); } break; } case SyntaxKind.YieldReturnStatement: { var yieldReturn = (YieldStatementSyntax)parent; SyntaxToken returnKeyword = yieldReturn.ReturnOrBreakKeyword; if (!returnKeyword.TrailingTrivia.Any()) { YieldStatementSyntax newNode = yieldReturn.Update(yieldReturn.YieldKeyword, returnKeyword.WithTrailingTrivia(Space), newExpression, yieldReturn.SemicolonToken); return(document.ReplaceNodeAsync(yieldReturn, newNode, cancellationToken)); } break; } case SyntaxKind.AwaitExpression: { var awaitExpression = (AwaitExpressionSyntax)parent; SyntaxToken awaitKeyword = awaitExpression.AwaitKeyword; if (!awaitKeyword.TrailingTrivia.Any()) { AwaitExpressionSyntax newNode = awaitExpression.Update(awaitKeyword.WithTrailingTrivia(Space), newExpression); return(document.ReplaceNodeAsync(awaitExpression, newNode, cancellationToken)); } break; } } } return(document.ReplaceNodeAsync(parenthesizedExpression, newExpression, cancellationToken)); }
public virtual void VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { DefaultVisit(node); }
public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) { var newExpression = (ExpressionSyntax)node.Expression.Accept(this); // Remove unnecessary parentheses around non-binary expressions if (!(newExpression is BinaryExpressionSyntax)) { return newExpression .WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); } else { return node.Expression != newExpression ? node.WithExpression(newExpression) : node; } }
public ParenthesizedExpressionTranslation(ParenthesizedExpressionSyntax syntax, SyntaxTranslation parent) : base(syntax, parent) { Expression = syntax.Expression.Get<ExpressionTranslation>(this); }