예제 #1
0
        public IChameleonNode ReSync(CachingLexer cachingLexer, TreeTextRange changedRange, int insertedTextLen)
        {
            TreeTextRange oldRange = this.GetTreeTextRange();

            Logger.Assert(changedRange.ContainedIn(oldRange), "The condition “changedRange.ContainedIn(oldRange)” is false.");

            int newLength = oldRange.Length - changedRange.Length + insertedTextLen;

            // Find starting comment
            if (!cachingLexer.FindTokenAt(oldRange.StartOffset.Offset) ||
                cachingLexer.TokenType != GetTokenType() ||
                cachingLexer.TokenStart != oldRange.StartOffset.Offset ||
                cachingLexer.TokenEnd != oldRange.StartOffset.Offset + newLength)
            {
                return(null);
            }

            LeafElementBase element = TreeElementFactory.CreateLeafElement(cachingLexer.TokenType, new ProjectedBuffer(cachingLexer.Buffer, new TextRange(cachingLexer.TokenStart, cachingLexer.TokenStart + newLength)), 0, newLength);
            var             comment = element as Comment;

            if (comment == null || CommentType != comment.CommentType)
            {
                return(null);
            }
            return(comment);
        }
예제 #2
0
        protected override TreeElement createToken()
        {
            LeafElementBase element = TreeElementFactory.CreateLeafElement(myLexer.TokenType, myLexer.Buffer, myLexer.TokenStart, myLexer.TokenEnd);

            SetOffset(element, myLexer.TokenStart);
            myLexer.Advance();
            return(element);
        }
예제 #3
0
        private LeafElementBase CreateCurrentToken()
        {
            T4TokenNodeType tokenType = GetTokenType();

            Assertion.AssertNotNull(tokenType, "tokenType == null");
            LeafElementBase token = tokenType.Create(_builderLexer.Buffer, new TreeOffset(_builderLexer.TokenStart), new TreeOffset(_builderLexer.TokenEnd));

            return(token);
        }
예제 #4
0
        /// <summary>
        /// Inserts a newline in front of the Node provided.
        /// </summary>
        /// <param name="currentNode">
        /// The node to insert in front of.
        /// </param>
        /// <returns>
        /// The inserted ITreeNode.
        /// </returns>
        public static ITreeNode InsertNewLineBefore(this ITreeNode currentNode)
        {
            LeafElementBase leafElement = GetLeafElement();

            using (WriteLockCookie.Create(true))
            {
                LowLevelModificationUtil.AddChildBefore(currentNode, new[] { leafElement });
            }

            return(leafElement);
        }
예제 #5
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);
                }
            }
        }
예제 #6
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);
                }
            }
        }
예제 #7
0
        protected override void ProcessLeafElement(TreeElement element)
        {
            int leafOffset = GetLeafOffset(element).Offset;

            // Check if some tokens are missed before this leaf
            if (myLexer.TokenType != null && myLexer.TokenStart < leafOffset)
            {
                // Find out the right place to insert tokens to
                TreeElement      anchor = element;
                CompositeElement parent = anchor.parent;
                while (anchor == parent.firstChild && parent.parent != null)
                {
                    anchor = parent;
                    parent = parent.parent;
                }

                // proceed with inserting tokens
                while (myLexer.TokenType != null && myLexer.TokenStart < leafOffset)
                {
                    LeafElementBase token = CreateMissingToken();

                    parent.AddChildBefore(token, anchor);

                    myLexer.Advance();
                }
            }

            // skip all tokens which lie inside given leaf element
            int leafEndOffset = leafOffset + element.GetTextLength();

            if ((element is IClosedChameleonBody) && (myLexer is CachingLexer))
            {
                ((CachingLexer)myLexer).FindTokenAt(leafEndOffset);
            }
            else
            {
                while (myLexer.TokenType != null && myLexer.TokenStart < leafEndOffset)
                {
                    myLexer.Advance();
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Fixes the spacing of the using directives in a given file or namespace block
        /// to match the specified configuration. (The directives must already be in
        /// the correct order.)
        /// </summary>
        /// <param name="holder">The file or namespace block in which to fix the spacing
        /// of using directives (if any are present).</param>
        /// <param name="configuration">The configuration determining the correct spacing.</param>
        public static void FixSpacing(
            ICSharpTypeAndNamespaceHolderDeclaration holder,
            OrderUsingsConfiguration configuration)
        {
            // The reordering proceeds one item at a time, so we just keep reapplying it
            // until there's nothing left to do.
            // To avoid hanging VS in the event that an error in the logic causes the
            // sequence of modifications not to terminate, we ensure we don't try to
            // apply more changes than there are either using directives or blank
            // lines in the usings list.
            int tries     = 0;
            int itemCount = 0;

            while (tries == 0 || tries <= itemCount)
            {
                List <UsingDirectiveOrSpace> items = ImportReader.ReadImports(holder);
                if (items == null)
                {
                    return;
                }

                itemCount = items.Count;
                List <UsingDirective>         imports;
                List <List <UsingDirective> > requiredOrderByGroups;
                ImportInspector.FlattenImportsAndDetermineOrderAndSpacing(
                    configuration, items, out imports, out requiredOrderByGroups);

                SpaceChange nextChange = ImportInspector.GetNextSpacingModification(requiredOrderByGroups, items);
                if (nextChange != null)
                {
                    IUsingDirective usingBeforeSpace = holder.Imports[nextChange.Index - 1];
                    if (nextChange.ShouldInsert)
                    {
                        using (WriteLockCookie.Create())
                        {
                            var newLineText = new StringBuffer("\r\n");

                            LeafElementBase newLine = TreeElementFactory.CreateLeafElement(
                                CSharpTokenType.NEW_LINE, newLineText, 0, newLineText.Length);
                            LowLevelModificationUtil.AddChildAfter(usingBeforeSpace, newLine);
                        }
                    }
                    else
                    {
                        var syb = usingBeforeSpace.NextSibling;
                        for (; syb != null && !(syb is IUsingDirective); syb = syb.NextSibling)
                        {
                            if (syb.NodeType == CSharpTokenType.NEW_LINE)
                            {
                                LowLevelModificationUtil.DeleteChild(syb);
                            }
                        }
                    }
                }
                else
                {
                    break;
                }

                tries += 1;
            }
        }