Example #1
0
        /// <summary>
        /// Code must not contain empty statements.
        /// </summary>
        /// <param name="node">
        /// The node to process.
        /// </param>
        private void CodeMustNotContainEmptyStatements(ITreeNode node)
        {
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ITokenNode tokenNode = currentNode as ITokenNode;

                    if (tokenNode.GetTokenType() == CSharpTokenType.SEMICOLON && !(tokenNode.Parent is IForStatement))
                    {
                        ITokenNode nextNonWhitespaceToken = Utils.GetFirstNonWhitespaceTokenToRight(tokenNode);

                        while (nextNonWhitespaceToken.GetTokenType() == CSharpTokenType.SEMICOLON)
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                if (nextNonWhitespaceToken.GetNextToken().GetTokenType() == CSharpTokenType.WHITE_SPACE)
                                {
                                    LowLevelModificationUtil.DeleteChild(nextNonWhitespaceToken.GetNextToken());
                                }

                                // remove the spare semi colon
                                LowLevelModificationUtil.DeleteChild(nextNonWhitespaceToken);
                                nextNonWhitespaceToken = Utils.GetFirstNonWhitespaceTokenToRight(tokenNode);
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    this.CodeMustNotContainEmptyStatements(currentNode.FirstChild);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Preprocessor keywords must not be preceded by space.
        /// </summary>
        /// <param name="node">
        /// The node to use.
        /// </param>
        public static void PreprocessorKeywordsMustNotBePrecededBySpace(ITreeNode node)
        {
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is IPreprocessorDirective)
                {
                    IPreprocessorDirective preprocessorDirectiveNode = currentNode as IPreprocessorDirective;

                    TreeOffset directiveTokenNodeOffset = preprocessorDirectiveNode.Directive.GetTreeStartOffset();

                    TreeOffset numberSignTokenNodeOffset = preprocessorDirectiveNode.NumberSign.GetTreeStartOffset();

                    if (directiveTokenNodeOffset - 1 != numberSignTokenNodeOffset)
                    {
                        // There is a gap between them
                        ITokenNode tokenNode = preprocessorDirectiveNode.NumberSign;

                        ITokenNode nextToken = tokenNode.GetNextToken();

                        using (WriteLockCookie.Create(true))
                        {
                            // remove the whitespace or new line
                            LowLevelModificationUtil.DeleteChild(nextToken);
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    PreprocessorKeywordsMustNotBePrecededBySpace(currentNode.FirstChild);
                }
            }
        }
Example #3
0
        /// <summary>
        /// Negative and positive signs must be spaced correctly.
        /// </summary>
        /// <param name="node">
        /// The node to use.
        /// </param>
        /// <param name="tokenToCheck">
        /// The token to check.
        /// </param>
        public static void NegativeAndPositiveSignsMustBeSpacedCorrectly(ITreeNode node, TokenNodeType tokenToCheck)
        {
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ITokenNode tokenNode = currentNode as ITokenNode;

                    if (tokenNode.GetTokenType() == tokenToCheck)
                    {
                        if (tokenNode.Parent is IOperatorExpression && !(tokenNode.Parent is IAdditiveExpression))
                        {
                            ITokenNode nextToken = tokenNode.GetNextToken();

                            if (nextToken.IsWhitespace())
                            {
                                using (WriteLockCookie.Create(true))
                                {
                                    // remove the whitespace or new line
                                    LowLevelModificationUtil.DeleteChild(nextToken);
                                }
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    NegativeAndPositiveSignsMustBeSpacedCorrectly(currentNode.FirstChild, tokenToCheck);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Element documentation headers must be preceded by blank line.
        /// </summary>
        /// <param name="node">
        /// The node.
        /// </param>
        private void ElementDocumentationHeadersMustBePrecededByBlankLine(ITreeNode node)
        {
            // go back to first new line to the left
            // thisnew line must be immeidately preceded by a new line and if not insert one
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is IDocCommentNode)
                {
                    ITokenNode token = currentNode as ITokenNode;
                    ITokenNode firstNewLineToLeft = Utils.GetFirstNewLineTokenToLeft(token);
                    if (firstNewLineToLeft != null)
                    {
                        ITokenNode tokenBeforeNewLine = firstNewLineToLeft.GetPrevToken();

                        // if we're the start of a code block then don't insert a new line.
                        if (!tokenBeforeNewLine.IsNewLine() && tokenBeforeNewLine.GetTokenType() != CSharpTokenType.LBRACE &&
                            tokenBeforeNewLine.GetTokenType() != CSharpTokenType.END_OF_LINE_COMMENT)
                        {
                            firstNewLineToLeft.GetNextToken().InsertNewLineBefore();
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    this.ElementDocumentationHeadersMustBePrecededByBlankLine(currentNode.FirstChild);
                }
            }
        }
        private void MakeFormat(FormattingRange range, IEnumerable <string> space)
        {
            PsiFormatterHelper.ReplaceSpaces(range.First, range.Last, space);

            // TODO: Move antiglueing logic into CalcSpaces()
            ITokenNode nextToken;
            ITokenNode prevToken = range.First.FindLastTokenIn();

            if (prevToken != null)
            {
                nextToken = prevToken.GetNextToken();
            }
            else
            {
                nextToken = range.First.NextSibling.FindFirstTokenIn();
                if (nextToken != null)
                {
                    prevToken = nextToken.GetPrevToken();
                }
            }

            if (prevToken != null && nextToken != null)
            {
                ITokenNode separator = Context.CodeFormatter.GetMinimalSeparator(prevToken, nextToken);
                if (separator != null)
                {
                    LowLevelModificationUtil.AddChildAfter(range.First, separator);
                }
            }
        }
Example #6
0
        /// <summary>
        /// Commas must be spaced correctly.
        /// </summary>
        /// <param name="node">
        /// The node to use.
        /// </param>
        public void EqualsMustBeSpacedCorrectly(ITreeNode node)
        {
            List <TokenNodeType> tokensThatCanBeLeftSideOfEquals = new List <TokenNodeType>
            {
                CSharpTokenType.WHITE_SPACE,
                CSharpTokenType.NE,
                CSharpTokenType.LT,
                CSharpTokenType.GT
            };

            const string WhiteSpace = " ";

            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ITokenNode tokenNode = currentNode as ITokenNode;

                    if (tokenNode.GetTokenType() == CSharpTokenType.EQ)
                    {
                        ITokenNode nextToken = tokenNode.GetNextToken();

                        ITokenNode previousToken = tokenNode.GetPrevToken();

                        if (!nextToken.IsWhitespace())
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                // insert a space
                                LeafElementBase leafElement = TreeElementFactory.CreateLeafElement(
                                    CSharpTokenType.WHITE_SPACE, new JetBrains.Text.StringBuffer(WhiteSpace), 0, WhiteSpace.Length);
                                LowLevelModificationUtil.AddChildBefore(nextToken, new ITreeNode[] { leafElement });
                            }
                        }

                        if (!tokensThatCanBeLeftSideOfEquals.Contains(previousToken.GetTokenType()))
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                // insert a space
                                LeafElementBase leafElement = TreeElementFactory.CreateLeafElement(
                                    CSharpTokenType.WHITE_SPACE, new JetBrains.Text.StringBuffer(WhiteSpace), 0, WhiteSpace.Length);
                                LowLevelModificationUtil.AddChildBefore(tokenNode, new ITreeNode[] { leafElement });
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    this.EqualsMustBeSpacedCorrectly(currentNode.FirstChild);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Remove empty comments.
        /// </summary>
        /// <param name="node">
        /// The node to process.
        /// </param>
        public static void RemoveEmptyComments(ITreeNode node)
        {
            // we don't remove empty lines from Element Doc Comments in here
            // the DeclarationHeader types take care of that.
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ICommentNode commentNode = currentNode as ICommentNode;
                    if (commentNode != null && !(commentNode is IDocCommentNode))
                    {
                        if (commentNode.CommentText.Trim() == string.Empty)
                        {
                            ITokenNode leftToken = Utils.GetFirstNewLineTokenToLeft((ITokenNode)currentNode);

                            ITokenNode rightToken = Utils.GetFirstNewLineTokenToRight((ITokenNode)currentNode);

                            if (leftToken == null)
                            {
                                leftToken = (ITokenNode)currentNode;
                            }
                            else
                            {
                                leftToken = leftToken.GetNextToken();
                            }

                            if (rightToken == null)
                            {
                                rightToken = (ITokenNode)currentNode;
                            }
                            else
                            {
                                currentNode = rightToken.GetNextToken();
                            }

                            using (WriteLockCookie.Create(true))
                            {
                                LowLevelModificationUtil.DeleteChildRange(leftToken, rightToken);
                            }
                        }
                    }
                }

                if (currentNode != null && currentNode.FirstChild != null)
                {
                    RemoveEmptyComments(currentNode.FirstChild);
                }
            }
        }
Example #8
0
        /// <summary>
        /// Delete child range.
        /// </summary>
        /// <param name="first">
        /// The first token to delete.
        /// </param>
        /// <param name="last">
        /// The last token to delete.
        /// </param>
        private static void DeleteChildRange(ITokenNode first, ITokenNode last)
        {
            using (WriteLockCookie.Create(true))
            {
                List <ITokenNode> a = new List <ITokenNode>();

                ITokenNode tokenNodeToStopAt = last.GetNextToken();
                for (ITokenNode foundToken = first; foundToken != tokenNodeToStopAt; foundToken = foundToken.GetNextToken())
                {
                    a.Add(foundToken);
                }

                foreach (ITokenNode tokenNode in a)
                {
                    LowLevelModificationUtil.DeleteChild(tokenNode);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Commas must be spaced correctly.
        /// </summary>
        /// <param name="node">
        /// The node to use.
        /// </param>
        public static void CommasMustBeSpacedCorrectly(ITreeNode node)
        {
            List <TokenNodeType> tokensThatCanBeRightSideOfComma = new List <TokenNodeType>
            {
                CSharpTokenType.NEW_LINE,
                CSharpTokenType.WHITE_SPACE,
                CSharpTokenType.RBRACKET,
                CSharpTokenType.GT,
                CSharpTokenType.COMMA,
                CSharpTokenType.RPARENTH
            };

            const string WhiteSpace = " ";

            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ITokenNode tokenNode = currentNode as ITokenNode;

                    if (tokenNode.GetTokenType() == CSharpTokenType.COMMA)
                    {
                        ITokenNode nextToken = tokenNode.GetNextToken();

                        if (!tokensThatCanBeRightSideOfComma.Contains(nextToken.GetTokenType()))
                        {
                            using (WriteLockCookie.Create(true))
                            {
                                // insert a space
                                LeafElementBase leafElement = TreeElementFactory.CreateLeafElement(
                                    CSharpTokenType.WHITE_SPACE, new JetBrains.Text.StringBuffer(WhiteSpace), 0, WhiteSpace.Length);
                                LowLevelModificationUtil.AddChildBefore(nextToken, new ITreeNode[] { leafElement });
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    CommasMustBeSpacedCorrectly(currentNode.FirstChild);
                }
            }
        }
Example #10
0
        /// <summary>
        /// Comments must not be followed by blank line.
        /// </summary>
        /// <param name="node">
        /// The node.
        /// </param>
        private void CommentsMustNotBeFollowedByBlankLine(ITreeNode node)
        {
            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ICommentNode && !(currentNode is IDocCommentNode))
                {
                    if (Utils.IsFirstNodeOnLine(currentNode))
                    {
                        ICommentNode tokenNode = currentNode as ICommentNode;

                        ITokenNode nextToken = tokenNode.GetNextToken();

                        if (nextToken != null && nextToken.IsNewLine())
                        {
                            ITokenNode nextNextToken = nextToken.GetNextToken();

                            if (nextNextToken != null)
                            {
                                ITokenNode nextNextNextToken = Utils.GetFirstNonWhitespaceTokenToRight(nextNextToken);

                                if (nextNextToken.IsNewLine() && !(nextNextNextToken is ICommentNode))
                                {
                                    ITreeNode rightNode = currentNode.FindFormattingRangeToRight();
                                    Utils.RemoveNewLineBefore(rightNode);
                                }
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    this.CommentsMustNotBeFollowedByBlankLine(currentNode.FirstChild);
                }
            }
        }
Example #11
0
        private static void SwapFileHeaderNode(ICSharpFile file, string newHeader)
        {
            ITreeRange existingHeaderRange = Utils.GetFileHeaderTreeRange(file);

            using (WriteLockCookie.Create(file.IsPhysical()))
            {
                ICommentNode newCommentNode;

                if (existingHeaderRange.IsEmpty)
                {
                    // existing header missing so add on a new line for our new header
                    newHeader += Environment.NewLine;

                    IWhitespaceNode node          = file.FirstChild as IWhitespaceNode;
                    bool            insertNewLine = true;
                    while (node != null)
                    {
                        if (node.IsNewLine)
                        {
                            insertNewLine = false;
                            break;
                        }

                        node = node.NextSibling as IWhitespaceNode;
                    }

                    if (insertNewLine)
                    {
                        newHeader += Environment.NewLine;
                    }

                    newCommentNode =
                        (ICommentNode)
                        CSharpTokenType.END_OF_LINE_COMMENT.Create(new JB::JetBrains.Text.StringBuffer(newHeader), new TreeOffset(0), new TreeOffset(newHeader.Length));

                    LowLevelModificationUtil.AddChildBefore(file.FirstChild, new ITreeNode[] { newCommentNode });
                }
                else
                {
                    ITokenNode lastToken = (ITokenNode)existingHeaderRange.Last;
                    ITokenNode nextToken = lastToken.GetNextToken();
                    if (nextToken != null)
                    {
                        ITokenNode nextNextToken = nextToken.GetNextToken();
                        if (nextNextToken != null)
                        {
                            ITokenNode nextNextNextToken = nextNextToken.GetNextToken();

                            if (!nextToken.IsNewLine() || !nextNextToken.IsNewLine())
                            {
                                newHeader += Environment.NewLine;
                            }

                            if (nextNextNextToken.GetTokenType() == CSharpTokenType.PP_SHARP && nextToken.IsNewLine() && nextNextToken.IsNewLine())
                            {
                                newHeader += Environment.NewLine;
                            }

                            newCommentNode =
                                (ICommentNode)
                                CSharpTokenType.END_OF_LINE_COMMENT.Create(
                                    new JB::JetBrains.Text.StringBuffer(newHeader), new TreeOffset(0), new TreeOffset(newHeader.Length));

                            LowLevelModificationUtil.ReplaceChildRange(existingHeaderRange.First, existingHeaderRange.Last, new ITreeNode[] { newCommentNode });
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Delete child range.
        /// </summary>
        /// <param name="first">
        /// The first token to delete.
        /// </param>
        /// <param name="last">
        /// The last token to delete.
        /// </param>
        private static void DeleteChildRange(ITokenNode first, ITokenNode last)
        {
            using (WriteLockCookie.Create(true))
            {
                List<ITokenNode> a = new List<ITokenNode>();

                ITokenNode tokenNodeToStopAt = last.GetNextToken();
                for (ITokenNode foundToken = first; foundToken != tokenNodeToStopAt; foundToken = foundToken.GetNextToken())
                {
                    a.Add(foundToken);
                }

                foreach (ITokenNode tokenNode in a)
                {
                    LowLevelModificationUtil.DeleteChild(tokenNode);
                }
            }
        }
        /// <summary>
        /// Gets the first non-whitespace token that occurs after the token passed in.
        /// </summary>
        /// <param name="tokenNode">
        /// The TokenNode to start at.
        /// </param>
        /// <returns>
        /// The first non-whitespace token.
        /// </returns>
        public static ITokenNode GetFirstNonWhitespaceTokenToRight(ITokenNode tokenNode)
        {
            ITokenNode currentToken = tokenNode.GetNextToken();
            while (currentToken != null && currentToken.IsWhitespace())
            {
                currentToken = currentToken.GetNextToken();
            }

            return currentToken;
        }
        /// <summary>
        /// Gets the first non-whitespace token that occurs after the token passed in.
        /// </summary>
        /// <param name="tokenNode">
        /// The TokenNode to start at.
        /// </param>
        /// <returns>
        /// The first non-whitespace token.
        /// </returns>
        public static ITokenNode GetFirstNewLineTokenToRight(ITokenNode tokenNode)
        {
            ITokenNode currentToken = tokenNode.GetNextToken();
            while (!currentToken.IsNewLine() && currentToken != null)
            {
                currentToken = currentToken.GetNextToken();
            }

            return currentToken;
        }
        /// <summary>
        /// True if the token is followed on the same line with a non-whitespace token.
        /// </summary>
        /// <param name="tokenNode">
        /// THe token to start at.
        /// </param>
        /// <returns>
        /// True or false.
        /// </returns>
        public static bool TokenHasNonWhitespaceTokenToRightOnSameLine(ITokenNode tokenNode)
        {
            ITokenNode currentToken = tokenNode.GetNextToken();
            if (currentToken == null)
            {
                return false;
            }

            while (currentToken.IsWhitespace() && !currentToken.IsNewLine() && currentToken != null)
            {
                currentToken = currentToken.GetNextToken();
            }

            return currentToken != null && !currentToken.IsNewLine();
        }
Example #16
0
        /// <summary>
        /// Closing curly bracket must be followed by blank line.
        /// </summary>
        /// <param name="node">
        /// The node to use.
        /// </param>
        public static void ClosingCurlyBracketMustBeFollowedByBlankLine(ITreeNode node)
        {
            // Closing curly brackets must be followed by a newline unless they are closing an object initializer or
            // followed by one of the endtokens defined here.
            // catch
            // finally
            // else
            // rbrace
            // dowhile
            // preprocessor directives
            List <TokenNodeType> tokensThatFollowClosingCurlyBracketWithoutNewLine = new List <TokenNodeType>
            {
                CSharpTokenType.RBRACE,
                CSharpTokenType.DO_KEYWORD,
                CSharpTokenType.ELSE_KEYWORD,
                CSharpTokenType.CATCH_KEYWORD,
                CSharpTokenType.FINALLY_KEYWORD
            };

            List <TokenNodeType> objectInitializerFollowers = new List <TokenNodeType>
            {
                CSharpTokenType.AS_KEYWORD,
                CSharpTokenType.IS_KEYWORD,
                CSharpTokenType.COMMA,
                CSharpTokenType.SEMICOLON,
                CSharpTokenType.DOT,
                CSharpTokenType.QUEST,
                CSharpTokenType.COLON,
                CSharpTokenType.RPARENTH,
                CSharpTokenType.EQEQ,
                CSharpTokenType.GE,
                CSharpTokenType.GT,
                CSharpTokenType.LE,
                CSharpTokenType.LT,
                CSharpTokenType.NE,
                CSharpTokenType.MINUS,
                CSharpTokenType.PLUS,
                CSharpTokenType.DIV,
                CSharpTokenType.ASTERISK,
                CSharpTokenType.PERC,
                CSharpTokenType.MINUSMINUS,
                CSharpTokenType.PLUSPLUS
            };

            for (ITreeNode currentNode = node; currentNode != null; currentNode = currentNode.NextSibling)
            {
                if (currentNode is ITokenNode)
                {
                    ITokenNode tokenNode = currentNode as ITokenNode;

                    if (tokenNode.GetTokenType() == CSharpTokenType.RBRACE)
                    {
                        IBlock blockNode = tokenNode.Parent as IBlock;

                        if (blockNode != null)
                        {
                            JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> lineNumberForLBrace = Utils.GetLineNumberForElement(blockNode.LBrace);
                            JB::JetBrains.Util.dataStructures.TypedIntrinsics.Int32 <DocLine> lineNumberForRBrace = Utils.GetLineNumberForElement(blockNode.RBrace);

                            if (lineNumberForLBrace != lineNumberForRBrace)
                            {
                                ITokenNode currentToken = tokenNode.GetNextToken();

                                int newLineCount = 0;
                                while (currentToken != null)
                                {
                                    if (currentToken.IsWhitespace())
                                    {
                                        if (currentToken.IsNewLine())
                                        {
                                            newLineCount++;
                                            if (newLineCount == 2)
                                            {
                                                // if we get 2 new lines we've already got a blank line after the closing curly bracket so jog on.
                                                break;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if ((!tokensThatFollowClosingCurlyBracketWithoutNewLine.Contains(currentToken.GetTokenType()) &&
                                             !objectInitializerFollowers.Contains(currentToken.GetTokenType())) ||
                                            (objectInitializerFollowers.Contains(currentToken.GetTokenType()) && newLineCount == 1))
                                        {
                                            tokenNode.GetNextToken().InsertNewLineBefore();
                                        }

                                        break;
                                    }

                                    currentToken = currentToken.GetNextToken();
                                }
                            }
                        }
                    }
                }

                if (currentNode.FirstChild != null)
                {
                    ClosingCurlyBracketMustBeFollowedByBlankLine(currentNode.FirstChild);
                }
            }
        }