Beispiel #1
0
        private static IValidationError SpacesInsideParenthesisCheck(IAstNode node, LintOptions options, bool projectedBuffer)
        {
            // There should be no space after (, [ or [[ and no space before ), ] or ]]
            // unless ] or ]] is preceded by a comma as in x[1, ]
            if (!options.SpacesInsideParenthesis || !(node is TokenNode t))
            {
                return(null);
            }
            var tp = node.Root.TextProvider;

            switch (t.Token.TokenType)
            {
            case RTokenType.OpenBrace:
            case RTokenType.OpenSquareBracket:
            case RTokenType.OpenDoubleSquareBracket:
                // x[1, OK x( 2) is not
                if (!tp.IsNewLineAfterPosition(node.End) && tp.IsWhitespaceAfterPosition(node.End - 1))
                {
                    var lineEnd = tp.IndexOf('\n', node.End);
                    lineEnd = lineEnd >= 0 ? lineEnd : tp.Length;
                    var text  = tp.GetText(TextRange.FromBounds(node.End, lineEnd));
                    var wsEnd = text.IndexWhere(ch => !char.IsWhiteSpace(ch)).FirstOrDefault();
                    wsEnd = wsEnd > 0 ? wsEnd + node.End : tp.Length;
                    return(new ValidationWarning(TextRange.FromBounds(node.End, wsEnd), Resources.Lint_SpaceAfterLeftParenthesis, ErrorLocation.Token));
                }
                break;

            case RTokenType.CloseBrace:
                // () is OK, (,,,) is OK, x( )  is not OK. But we do allow line break before )
                if (tp.IsWhitespaceBeforePosition(node.Start) && !tp.IsNewLineBeforePosition(node.Start))
                {
                    var i = node.Start - 1;
                    for (; i >= 0; i--)
                    {
                        if (!char.IsWhiteSpace(tp[i]) || tp[i] == '\r' || tp[i] == '\n')
                        {
                            i++;
                            break;
                        }
                    }
                    i = Math.Max(i, 0);
                    return(new ValidationWarning(TextRange.FromBounds(i, node.Start), Resources.Lint_SpaceBeforeClosingBrace, ErrorLocation.Token));
                }
                break;

            case RTokenType.CloseSquareBracket:
            case RTokenType.CloseDoubleSquareBracket:
                // x[1] is OK, x[1,] is not OK, should be x[1, ]
                var prevChar = node.Start > 0 ? tp[node.Start - 1] : '\0';
                if (!tp.IsWhitespaceAfterPosition(node.End - 1) && prevChar == ',')
                {
                    return(new ValidationWarning(node, Resources.Lint_NoSpaceBetweenCommaAndClosingBracket, ErrorLocation.Token));
                }
                break;
            }
            return(null);
        }
Beispiel #2
0
 private static IValidationError DoubleQuotesCheck(IAstNode node, LintOptions options, bool projectedBuffer)
 {
     // open_curly_linter: check that opening curly braces are never on their own line and are
     // always followed by a newline
     if (options.DoubleQuotes)
     {
         if (node is TokenNode t && t.Token.TokenType == RTokenType.String)
         {
             if (node.Root.TextProvider[node.Start] != '\"')
             {
                 return(new ValidationWarning(node, Resources.Lint_DoubleQuotes, ErrorLocation.Token));
             }
         }
     }
     return(null);
 }
Beispiel #3
0
 private static IValidationError OpenCurlyPositionCheck(IAstNode node, LintOptions options)
 {
     // open_curly_linter: check that opening curly braces are never on their own line
     // and are always followed by a newline
     if (options.OpenCurlyPosition)
     {
         if (node is TokenNode t && t.Token.TokenType == RTokenType.OpenCurlyBrace)
         {
             var tp = node.Root.TextProvider;
             if (!HasLineTextBeforePosition(tp, node.Start) || !tp.IsNewLineAfterPosition(node.End))
             {
                 return(new ValidationWarning(node, Resources.Lint_OpenCurlyPosition, ErrorLocation.Token));
             }
         }
     }
     return(null);
 }
Beispiel #4
0
 private static IValidationError InfixOperatorsSpacesCheck(IAstNode node, LintOptions options)
 {
     // infix_spaces_linter: check that all infix operators have spaces around them.
     if (options.SpacesAroundOperators)
     {
         if (node is IOperator op && !op.IsUnary && op is TokenOperator to)
         {
             var tp = node.Root.TextProvider;
             var t  = to.OperatorToken;
             if (!tp.IsWhitespaceBeforePosition(t.Start) || !tp.IsWhitespaceAfterPosition(t.End - 1))
             {
                 return(new ValidationWarning(t, Resources.Lint_OperatorSpaces, ErrorLocation.Token));
             }
         }
     }
     return(null);
 }
Beispiel #5
0
        private static IValidationError CloseCurlySeparateLineCheck(IAstNode node, LintOptions options, bool projectedBuffer)
        {
            // closed_curly_linter: check that closed curly braces should always be
            // on their own line unless they follow an else
            if (!options.CloseCurlySeparateLine)
            {
                return(null);
            }

            if (!(node is TokenNode t) || t.Token.TokenType != RTokenType.CloseCurlyBrace)
            {
                return(null);
            }

            // Special case {r in R Markdown
            if (projectedBuffer && IsRMarkdownBlock(node))
            {
                return(null);
            }

            // Check 'after' case first to we allow '{x})' or '{x},'
            var text = GetLineTextAfterPosition(node.Root.TextProvider, node.Start).TrimStart();

            // Handle '},', '})' and '} else'
            if (text.StartsWithOrdinal(",") || text.StartsWithOrdinal(")"))
            {
                return(null);
            }
            if (!string.IsNullOrWhiteSpace(text) && !text.StartsWithOrdinal("else"))
            {
                return(new ValidationWarning(node, Resources.Lint_CloseCurlySeparateLine, ErrorLocation.Token));
            }

            text = GetLineTextBeforePosition(node.Root.TextProvider, node.Start);
            // allow '{ }'
            if (string.IsNullOrWhiteSpace(text) || text.TrimEnd().EndsWithOrdinal("{"))
            {
                return(null);
            }
            return(new ValidationWarning(node, Resources.Lint_CloseCurlySeparateLine, ErrorLocation.Token));
        }
Beispiel #6
0
 private static IValidationError OpenCurlyPositionCheck(IAstNode node, LintOptions options, bool projectedBuffer)
 {
     // open_curly_linter: check that opening curly braces are never on their own line
     // and are always followed by a newline
     if (options.OpenCurlyPosition)
     {
         if (node is TokenNode t && t.Token.TokenType == RTokenType.OpenCurlyBrace)
         {
             var tp = node.Root.TextProvider;
             // Special case {r in R Markdown
             if (projectedBuffer && IsRMarkdownBlock(node))
             {
                 return(null);
             }
             if (!HasLineTextBeforePosition(tp, node.Start, out var unused) || !tp.IsNewLineAfterPosition(node.End))
             {
                 return(new ValidationWarning(node, Resources.Lint_OpenCurlyPosition, ErrorLocation.Token));
             }
         }
     }
     return(null);
 }
Beispiel #7
0
        private static IValidationError OpenCurlyPositionCheck(IAstNode node, LintOptions options, bool projectedBuffer)
        {
            // open_curly_linter: check that opening curly braces are never on their own line
            // and are always followed by a newline
            if (!options.OpenCurlyPosition)
            {
                return(null);
            }

            if (!(node is TokenNode t) || t.Token.TokenType != RTokenType.OpenCurlyBrace)
            {
                return(null);
            }

            // Special case {r in R Markdown
            if (projectedBuffer && IsRMarkdownBlock(node))
            {
                return(null);
            }

            var tp   = node.Root.TextProvider;
            var text = GetLineTextBeforePosition(tp, node.Start);

            if (string.IsNullOrWhiteSpace(text))
            {
                return(new ValidationWarning(node, Resources.Lint_OpenCurlyPosition, ErrorLocation.Token));
            }

            // allow '{ }'
            text = GetLineTextAfterPosition(tp, node.Start);
            if (string.IsNullOrWhiteSpace(text) || text.TrimStart().StartsWithOrdinal("}"))
            {
                return(null);
            }

            return(new ValidationWarning(node, Resources.Lint_OpenCurlyPosition, ErrorLocation.Token));
        }