示例#1
0
        public static FormattingSuggestion AnalyzeNewLineBeforeOrAfter(
            SyntaxToken token,
            ExpressionSyntax expression,
            NewLinePosition newLinePosition)
        {
            SyntaxToken previousToken = token.GetPreviousToken();

            if (newLinePosition == NewLinePosition.Before &&
                SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(previousToken.TrailingTrivia))
            {
                if (!token.LeadingTrivia.Any() &&
                    SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(token.TrailingTrivia) &&
                    SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(expression.GetLeadingTrivia()))
                {
                    return(FormattingSuggestion.AddNewLineBefore);
                }
            }
            else if (newLinePosition == NewLinePosition.After &&
                     SyntaxTriviaAnalysis.IsOptionalWhitespaceThenEndOfLineTrivia(previousToken.TrailingTrivia))
            {
                if (SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(token.LeadingTrivia) &&
                    SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(token.TrailingTrivia) &&
                    !expression.GetLeadingTrivia().Any())
                {
                    return(FormattingSuggestion.AddNewLineAfter);
                }
            }

            return(FormattingSuggestion.None);
        }
示例#2
0
        private static void AnalyzeArrowExpressionClause(SyntaxNodeAnalysisContext context)
        {
            var arrowExpressionClause = (ArrowExpressionClauseSyntax)context.Node;

            SyntaxToken arrowToken = arrowExpressionClause.ArrowToken;

            NewLinePosition newLinePosition = context.GetArrowTokenNewLinePosition();

            if (newLinePosition == NewLinePosition.None)
            {
                return;
            }

            FormattingSuggestion suggestion = FormattingAnalysis.AnalyzeNewLineBeforeOrAfter(arrowToken, arrowExpressionClause.Expression, newLinePosition);

            if (suggestion == FormattingSuggestion.AddNewLineBefore)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeArrowToken,
                    arrowToken.GetLocation(),
                    "before");
            }
            else if (suggestion == FormattingSuggestion.AddNewLineAfter)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeArrowToken,
                    arrowToken.GetLocation(),
                    properties: DiagnosticProperties.AnalyzerOption_Invert,
                    "after");
            }
        }
        private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxToken token, ExpressionSyntax expression)
        {
            NewLinePosition newLinePosition = context.GetEqualsSignNewLinePosition();

            if (newLinePosition == NewLinePosition.None)
            {
                return;
            }

            FormattingSuggestion suggestion = FormattingAnalysis.AnalyzeNewLineBeforeOrAfter(token, expression, newLinePosition);

            if (suggestion == FormattingSuggestion.AddNewLineBefore)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeEqualsToken,
                    token.GetLocation(),
                    "before");
            }
            else if (suggestion == FormattingSuggestion.AddNewLineAfter)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeEqualsToken,
                    token.GetLocation(),
                    properties: DiagnosticProperties.AnalyzerOption_Invert,
                    "after");
            }
        }
        private static void AnalyzeConditionalAccess(SyntaxNodeAnalysisContext context)
        {
            var conditionalAccess = (ConditionalAccessExpressionSyntax)context.Node;

            ExpressionSyntax left = conditionalAccess.Expression;

            if (left.IsMissing)
            {
                return;
            }

            ExpressionSyntax right = conditionalAccess.WhenNotNull;

            if (right.IsMissing)
            {
                return;
            }

            NewLinePosition newLinePosition = context.GetNullConditionalOperatorNewLinePosition();

            if (newLinePosition == NewLinePosition.None)
            {
                return;
            }

            SyntaxToken operatorToken = conditionalAccess.OperatorToken;

            if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(left, operatorToken, right))
            {
                if (newLinePosition == NewLinePosition.Before)
                {
                    DiagnosticHelpers.ReportDiagnostic(
                        context,
                        DiagnosticRules.PlaceNewLineAfterOrBeforeNullConditionalOperator,
                        operatorToken,
                        "before");
                }
            }
            else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(left, operatorToken, right) &&
                     newLinePosition == NewLinePosition.After)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeNullConditionalOperator,
                    Location.Create(conditionalAccess.SyntaxTree, operatorToken.Span),
                    DiagnosticProperties.NewLinePosition_After,
                    "after");
            }
        }
        private static void AnalyzeBinaryExpression(SyntaxNodeAnalysisContext context)
        {
            var binaryExpression = (BinaryExpressionSyntax)context.Node;

            ExpressionSyntax left = binaryExpression.Left;

            if (left.IsMissing)
            {
                return;
            }

            ExpressionSyntax right = binaryExpression.Right;

            if (right.IsMissing)
            {
                return;
            }

            NewLinePosition newLinePosition = context.GetBinaryExpressionNewLinePosition();

            if (newLinePosition == NewLinePosition.None)
            {
                return;
            }

            if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(left, binaryExpression.OperatorToken, right))
            {
                if (newLinePosition == NewLinePosition.Before)
                {
                    DiagnosticHelpers.ReportDiagnostic(
                        context,
                        DiagnosticRules.PlaceNewLineAfterOrBeforeBinaryOperator,
                        Location.Create(binaryExpression.SyntaxTree, binaryExpression.OperatorToken.Span.WithLength(0)),
                        "before");
                }
            }
            else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(left, binaryExpression.OperatorToken, right) &&
                     newLinePosition == NewLinePosition.After)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeBinaryOperator,
                    Location.Create(binaryExpression.SyntaxTree, binaryExpression.OperatorToken.Span.WithLength(0)),
                    properties: DiagnosticProperties.AnalyzerOption_Invert,
                    "after");
            }
        }
        private static bool TryGetNewLinePosition(
            AnalyzerConfigOptions configOptions,
            ConfigOptionDescriptor option,
            out NewLinePosition newLinePosition)
        {
            if (ConfigOptions.TryGetValue(configOptions, option, out string rawValue))
            {
                if (string.Equals(rawValue, "before", StringComparison.OrdinalIgnoreCase))
                {
                    newLinePosition = NewLinePosition.Before;
                    return(true);
                }
                else if (string.Equals(rawValue, "after", StringComparison.OrdinalIgnoreCase))
                {
                    newLinePosition = NewLinePosition.After;
                    return(true);
                }
            }

            newLinePosition = NewLinePosition.None;
            return(false);
        }
 public override ElementInfo <ParameterSyntax> CreateInfo(ParameterSyntax node, int insertIndex, NewLinePosition newLinePosition)
 {
     return(new ParamElementInfo(node, insertIndex, newLinePosition));
 }
 public ParamElementInfo(ParameterSyntax node, int insertIndex, NewLinePosition newLinePosition)
     : base(node, insertIndex, newLinePosition)
 {
 }
 public abstract ElementInfo <TNode> CreateInfo(TNode node, int insertIndex, NewLinePosition newLinePosition);
示例#10
0
 protected ElementInfo(TNode node, int insertIndex, NewLinePosition newLinePosition)
 {
     Node            = node;
     InsertIndex     = insertIndex;
     NewLinePosition = newLinePosition;
 }
示例#11
0
 public static NewLinePosition GetNullConditionalOperatorNewLinePosition(this SyntaxNodeAnalysisContext context, NewLinePosition defaultValue = NewLinePosition.None)
 {
     return(context.GetConfigOptions().GetNullConditionalOperatorNewLinePosition(defaultValue));
 }
示例#12
0
 public static NewLinePosition GetNullConditionalOperatorNewLinePosition(this AnalyzerConfigOptions configOptions, NewLinePosition defaultValue = NewLinePosition.None)
 {
     return((TryGetNewLinePosition(configOptions, ConfigOptions.NullConditionalOperatorNewLine, out NewLinePosition newLinePosition))
         ? newLinePosition
         : defaultValue);
 }
        private static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context)
        {
            var conditionalExpression = (ConditionalExpressionSyntax)context.Node;

            ExpressionSyntax condition = conditionalExpression.Condition;

            if (condition.IsMissing)
            {
                return;
            }

            ExpressionSyntax whenTrue = conditionalExpression.WhenTrue;

            if (whenTrue.IsMissing)
            {
                return;
            }

            NewLinePosition newLinePosition = context.GetConditionalExpressionNewLinePosition();

            if (newLinePosition == NewLinePosition.None)
            {
                return;
            }

            if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(condition, conditionalExpression.QuestionToken, whenTrue))
            {
                if (newLinePosition == NewLinePosition.Before)
                {
                    ReportDiagnostic(conditionalExpression.QuestionToken, ImmutableDictionary <string, string> .Empty, "before");
                    return;
                }
            }
            else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(condition, conditionalExpression.QuestionToken, whenTrue))
            {
                if (newLinePosition == NewLinePosition.After)
                {
                    ReportDiagnostic(conditionalExpression.QuestionToken, DiagnosticProperties.AnalyzerOption_Invert, "after");
                    return;
                }
            }

            ExpressionSyntax whenFalse = conditionalExpression.WhenFalse;

            if (!whenFalse.IsMissing)
            {
                if (SyntaxTriviaAnalysis.IsTokenFollowedWithNewLineAndNotPrecededWithNewLine(whenTrue, conditionalExpression.ColonToken, whenFalse))
                {
                    if (newLinePosition == NewLinePosition.Before)
                    {
                        ReportDiagnostic(conditionalExpression.ColonToken, ImmutableDictionary <string, string> .Empty, "before");
                    }
                }
                else if (SyntaxTriviaAnalysis.IsTokenPrecededWithNewLineAndNotFollowedWithNewLine(whenTrue, conditionalExpression.ColonToken, whenFalse))
                {
                    if (newLinePosition == NewLinePosition.After)
                    {
                        ReportDiagnostic(conditionalExpression.ColonToken, DiagnosticProperties.AnalyzerOption_Invert, "after");
                    }
                }
            }

            void ReportDiagnostic(
                SyntaxToken token,
                ImmutableDictionary <string, string> properties,
                string messageArg)
            {
                DiagnosticHelpers.ReportDiagnostic(
                    context,
                    DiagnosticRules.PlaceNewLineAfterOrBeforeConditionalOperator,
                    Location.Create(token.SyntaxTree, token.Span.WithLength(0)),
                    properties: properties,
                    messageArg);
            }
        }
示例#14
0
        public static Task <Document> FixCallChainAsync(
            Document document,
            ExpressionSyntax expression,
            TextSpan span,
            CancellationToken cancellationToken = default)
        {
            NewLinePosition conditionalAccessOperatorNewLinePosition = document.GetConfigOptions(expression.SyntaxTree).GetNullConditionalOperatorNewLinePosition(NewLinePosition.After);

            IndentationAnalysis indentationAnalysis = AnalyzeIndentation(expression, cancellationToken);
            string indentation             = indentationAnalysis.GetIncreasedIndentation();
            string endOfLineAndIndentation = DetermineEndOfLine(expression).ToString() + indentation;

            var textChanges = new List <TextChange>();
            int prevIndex   = expression.Span.End;

            foreach (SyntaxNode node in new MethodChain(expression))
            {
                SyntaxKind kind = node.Kind();

                if (kind == SyntaxKind.SimpleMemberAccessExpression)
                {
                    var memberAccess = (MemberAccessExpressionSyntax)node;

                    if (!SetIndentation(memberAccess.OperatorToken))
                    {
                        break;
                    }
                }
                else if (kind == SyntaxKind.MemberBindingExpression)
                {
                    var memberBinding = (MemberBindingExpressionSyntax)node;

                    if (!memberBinding.HasLeadingTrivia)
                    {
                        SyntaxToken prevToken = memberBinding.GetFirstToken().GetPreviousToken();

                        if (prevToken.IsKind(SyntaxKind.QuestionToken) &&
                            prevToken.IsParentKind(SyntaxKind.ConditionalAccessExpression))
                        {
                            var conditionalAccess = (ConditionalAccessExpressionSyntax)prevToken.Parent;

                            if (expression.SyntaxTree.IsMultiLineSpan(TextSpan.FromBounds(conditionalAccess.Expression.Span.End, conditionalAccess.OperatorToken.SpanStart)))
                            {
                                continue;
                            }
                        }
                    }

                    if (conditionalAccessOperatorNewLinePosition == NewLinePosition.After &&
                        !SetIndentation(memberBinding.OperatorToken))
                    {
                        break;
                    }
                }
                else if (kind == SyntaxKind.ConditionalAccessExpression)
                {
                    var conditionalAccess = (ConditionalAccessExpressionSyntax)node;

                    if (conditionalAccessOperatorNewLinePosition == NewLinePosition.Before ||
                        expression.SyntaxTree.IsMultiLineSpan(TextSpan.FromBounds(conditionalAccess.Expression.Span.End, conditionalAccess.OperatorToken.SpanStart)))
                    {
                        if (!SetIndentation(conditionalAccess.OperatorToken))
                        {
                            break;
                        }
                    }
                }
            }

            FormattingVerifier.VerifyChangedSpansAreWhitespace(expression, textChanges);

            return(document.WithTextChangesAsync(textChanges, cancellationToken));

            bool SetIndentation(SyntaxToken token)
            {
                if (token.Span.End > span.End)
                {
                    return(true);
                }

                if (token.SpanStart < span.Start)
                {
                    return(false);
                }

                SyntaxTriviaList leading = token.LeadingTrivia;

                SyntaxTriviaList.Reversed.Enumerator en = leading.Reverse().GetEnumerator();

                if (!en.MoveNext())
                {
                    SyntaxTrivia trivia = expression.FindTrivia(token.SpanStart - 1);

                    string newText = (trivia.IsEndOfLineTrivia()) ? indentation : endOfLineAndIndentation;

                    textChanges.Add(new TextSpan(token.SpanStart, 0), newText);

                    SetIndentation2(token, prevIndex);
                    prevIndex = (trivia.IsEndOfLineTrivia()) ? trivia.SpanStart : token.SpanStart;
                    return(true);
                }

                SyntaxTrivia last = en.Current;

                SyntaxKind kind = en.Current.Kind();

                if (kind == SyntaxKind.WhitespaceTrivia)
                {
                    if (en.Current.Span.Length != indentation.Length)
                    {
                        if (!en.MoveNext() ||
                            en.Current.IsEndOfLineTrivia())
                        {
                            SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1);

                            if (trivia.IsEndOfLineTrivia())
                            {
                                textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation);
                                SetIndentation2(token, prevIndex);
                                prevIndex = trivia.SpanStart;
                                return(true);
                            }
                        }
                    }
                }
                else if (kind == SyntaxKind.EndOfLineTrivia)
                {
                    SyntaxTrivia trivia = expression.FindTrivia(token.FullSpan.Start - 1);

                    if (trivia.IsEndOfLineTrivia())
                    {
                        textChanges.Add((leading.IsEmptyOrWhitespace()) ? leading.Span : last.Span, indentation);
                        SetIndentation2(token, prevIndex);
                        prevIndex = trivia.SpanStart;
                        return(true);
                    }
                }

                prevIndex = leading.Span.Start - 1;
                return(true);
            }

            void SetIndentation2(SyntaxToken token, int endIndex)
            {
                ImmutableArray <IndentationInfo> indentations = FindIndentations(
                    expression,
                    TextSpan.FromBounds(token.SpanStart, endIndex))
                                                                .ToImmutableArray();

                if (!indentations.Any())
                {
                    return;
                }

                int firstIndentationLength = indentations[0].Span.Length;

                for (int j = 0; j < indentations.Length; j++)
                {
                    IndentationInfo indentationInfo = indentations[j];

                    string replacement = indentation + indentationAnalysis.GetSingleIndentation();

                    if (j > 0 &&
                        indentationInfo.Span.Length > firstIndentationLength)
                    {
                        replacement += indentationInfo.ToString().Substring(firstIndentationLength);
                    }

                    if (indentationInfo.Span.Length != replacement.Length)
                    {
                        textChanges.Add(indentationInfo.Span, replacement);
                    }
                }
            }
        }