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); }
protected override TreeElement createToken() { LeafElementBase element = TreeElementFactory.CreateLeafElement(myLexer.TokenType, myLexer.Buffer, myLexer.TokenStart, myLexer.TokenEnd); SetOffset(element, myLexer.TokenStart); myLexer.Advance(); return(element); }
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); }
/// <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); }
/// <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); } } }
/// <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); } } }
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(); } } }
/// <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; } }