private static int GetDepth(SyntaxNodeOrToken syntax, int depth = 0) { if (syntax.IsNode) { return(syntax.ChildNodesAndTokens().Count == 0 ? depth : syntax.ChildNodesAndTokens().Max(x => GetDepth(x, depth + 1))); } return((syntax.AsToken().HasLeadingTrivia || syntax.AsToken().HasTrailingTrivia) ? depth + 1 : depth); }
private void AssertNodesAreEquivalent(SyntaxNodeOrToken expectedNode, SyntaxNodeOrToken actualNode) { Assert.Equal(expectedNode.Kind(), actualNode.Kind()); Assert.Equal(expectedNode.FullSpan, actualNode.FullSpan); Assert.Equal(expectedNode.ChildNodesAndTokens().Count, actualNode.ChildNodesAndTokens().Count); for (var i = 0; i < expectedNode.ChildNodesAndTokens().Count; i++) { AssertNodesAreEquivalent(expectedNode.ChildNodesAndTokens()[i], actualNode.ChildNodesAndTokens()[i]); } }
private void WriteLeaves(IEnumerable <CSNode> fragmentLeaves, SyntaxNodeOrToken roslynFragmentRoot) { var writableLeaves = fragmentLeaves.Where(l => l.CouldBeWritten); using (StringWriter strWriter = new StringWriter()) { foreach (var leaf in writableLeaves) { if (leaf.IsExistingRoslynNode && leaf.UseRoslynMatchToWrite) { var roslynNode = FindCorrespondingRoslynNodeOrToken(roslynFragmentRoot.ChildNodesAndTokens(), leaf); if (roslynNode != null) { strWriter.Write(roslynNode.ToFullString()); } } else if (leaf.IsExistingRoslynNode) { var uShortSyntaxKind = ushort.Parse(leaf.STInfo); strWriter.Write((SyntaxKind)uShortSyntaxKind); } else { strWriter.Write($" {leaf.ToString()}"); } } AnnounceNewFragment(strWriter.ToString()); } }
private static bool TryFindNodeOrToken( SyntaxNodeOrToken node, SyntaxKind kind, ref int occurrence, ref SyntaxNodeOrToken foundNode ) { if (node.IsKind(kind)) { occurrence--; if (occurrence == 0) { foundNode = node; return(true); } } // we should probably did into trivia if this is a Token, but we won't foreach (var child in node.ChildNodesAndTokens()) { if (TryFindNodeOrToken(child, kind, ref occurrence, ref foundNode)) { return(true); } } return(false); }
private static void GatherNodes(SyntaxNodeOrToken node, HashSet<GreenNode> hashSet) { hashSet.Add(node.UnderlyingNode); foreach (var child in node.ChildNodesAndTokens()) { GatherNodes(child, hashSet); } }
private static SyntaxNodeOrToken GetLastNodeOrToken(SyntaxNodeOrToken nodeOrToken) { SyntaxNodeOrToken last = default; var children = nodeOrToken.ChildNodesAndTokens().ToArray(); while (children.Length > 0) { last = children[^ 1];
private static void GetDirectiveTriviaRecursively(SyntaxNodeOrToken node, List <SyntaxNode> list) { if (node == null) { return; } if (list == null) { list = new List <SyntaxNode>(); } foreach (var child in node.ChildNodesAndTokens()) { if (child.ContainsDirectives) { if (child.IsToken) { foreach (var trivia in ((SyntaxToken)child).GetAllTrivia()) { if (trivia.IsDirective && trivia.HasStructure) { var trivianode = trivia.GetStructure(); switch (trivianode.Kind()) { case SyntaxKind.IfDirectiveTrivia: case SyntaxKind.ElseDirectiveTrivia: case SyntaxKind.ElifDirectiveTrivia: case SyntaxKind.EndIfDirectiveTrivia: list.Add(trivianode); break; default: GetDirectiveTriviaRecursively(trivianode, list); break; } } } } else { switch (child.Kind()) { case SyntaxKind.IfDirectiveTrivia: case SyntaxKind.ElseDirectiveTrivia: case SyntaxKind.ElifDirectiveTrivia: case SyntaxKind.EndIfDirectiveTrivia: list.Add((SyntaxNode)child); break; default: GetDirectiveTriviaRecursively(child, list); break; } } } } }
private Item(SyntaxNodeOrToken x) { this.SyntaxNodeOrToken = x; this.ChildList = x.ChildNodesAndTokens(); this.Language = IsVB(x.Language) ? TargetLanguage.VB : TargetLanguage.CS; if (this.SyntaxNodeOrToken.IsToken) { Value = this.Token = x.AsToken(); Text = this.Token.Text; if (this.Language == TargetLanguage.VB) { foreach (var k in kindsVB) { if (this.Token.IsKind(k)) { this.Kind = k; break; } } } else { foreach (var k in kindsCS) { if (this.Token.IsKind(k)) { this.Kind = k; break; } } } this.ItemType = ItemType.Token; } else { Value = this.Node = x.AsNode(); if (this.Node is VB.VisualBasicSyntaxNode) { var node = (VB.VisualBasicSyntaxNode) this.Node; this.Kind = node.Kind(); this.Text = this.Kind.ToString(); } else { this.Text = ((CS.CSharpSyntaxNode)Node).Kind().ToString(); //Text = this.Node.ToString(); } this.ItemType = ItemType.Node; } }
private static CodeCompletionExpression FindExpression(SyntaxNodeOrToken node, int endOfCodeIdx) { if (node.FullSpan.End == endOfCodeIdx && node.Kind() == SyntaxKind.SimpleMemberAccessExpression) { var children = node.ChildNodesAndTokens(); return(new CodeCompletionExpression { Expression = children.First().ToString(), Prefix = children.ElementAt(2).ToString(), }); } foreach (var c in node.ChildNodesAndTokens()) { var expression = FindExpression(c, endOfCodeIdx); if (expression != NoExpression) { return(expression); } } return(NoExpression); }
private static void GetRebuiltNodes(SyntaxNodeOrToken newNode, HashSet<GreenNode> hashSet, ArrayBuilder<SyntaxNodeOrToken> nodes) { if (hashSet.Contains(newNode.UnderlyingNode)) { return; } nodes.Add(newNode); foreach (var child in newNode.ChildNodesAndTokens()) { GetRebuiltNodes(child, hashSet, nodes); } }
/// <summary> /// Search the Children of this object for an EOL Trivia after the position of the replacedNode /// </summary> /// <param name="objToSearch">The Node or Token to search the children of (and then itself) for a SyntaxKind.EndOfLineTrivia</param> /// <param name="endReplacedSpan">The character position at the end of the replacedNode - dont want EOLs from before the replacement</param> /// <param name="foundEOL">the object to get back to the top when we find it</param> /// <returns>True if we found it</returns> bool FindEOLAfter(SyntaxNodeOrToken objToSearch, int endReplacedSpan, ref SyntaxTrivia foundEOL) { // Guard for the object is before the replacedNode if (objToSearch.FullSpan.End < endReplacedSpan) { return(false); } // Search each child for the trivia foreach (SyntaxNodeOrToken n in objToSearch.ChildNodesAndTokens()) { if (n.FullSpan.End < endReplacedSpan) { continue; } if (FindEOLAfter(n, endReplacedSpan, ref foundEOL)) { return(true); } } // Now search this object foreach (SyntaxTrivia item in objToSearch.GetLeadingTrivia()) { //Dont bother if the start of the element is before the replaced Node if (objToSearch.FullSpan.Start < endReplacedSpan) { continue; } if (item.Kind() == SyntaxKind.EndOfLineTrivia) { foundEOL = item; return(true); } } foreach (SyntaxTrivia item in objToSearch.GetTrailingTrivia()) { if (item.Kind() == SyntaxKind.EndOfLineTrivia) { foundEOL = item; return(true); } } return(false); }
private SyntaxNodeOrToken FindChild(SyntaxNodeOrToken current, PathSegment segment) { var ordinal = segment.Ordinal; foreach (var child in current.ChildNodesAndTokens()) { if (!_trackKinds || child.RawKind == segment.Kind) { if (ordinal == 0) { return(child); } else { ordinal--; } } } return(default);
public void Add(SyntaxNodeOrToken newNode, int precedingId, int currentDepth, int maxDepth = int.MaxValue) { Counter += 1; _parentIds.Add(precedingId); if (currentDepth >= maxDepth) { return; } // TODO: Throw, or error check or something. Debug.Assert(newNode.Kind() == Kind, "Uh oh. Kinds must be the same at ShwingNodes."); var newChildren = newNode.ChildNodesAndTokens(); ShwingNode lastTouchedNode = null; for (int i = 0; i < newChildren.Count; i++) { var newKid = newChildren[i]; if (i == Children.Count) { Children.Add(new List <ShwingNode>()); } var j = Children[i].FindIndex(x => x.Kind == newKid.Kind()); var lastId = lastTouchedNode?.Id ?? -2; if (j != -1) { Children[i][j].Add(newKid, lastId, currentDepth + 1, maxDepth); lastTouchedNode = Children[i][j]; } else { lastTouchedNode = new ShwingNode(newKid, lastId, currentDepth + 1, maxDepth); Children[i].Add(lastTouchedNode); } } }
/// <summary> /// Prints full hierarchy of the specified syntax node or token as string representation. /// </summary> /// <param name="builder">The builder used to create a string representation.</param> /// <param name="nodeOrToken">The syntax node or token to print.</param> /// <param name="depth">The initial indent depth.</param> /// <param name="indent">The indent value used for nested nodes.</param> public static void PrintSyntaxNodeOrToken(StringBuilder builder, SyntaxNodeOrToken nodeOrToken, int depth = 0, int indent = 4) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (depth < 0) { throw new ArgumentOutOfRangeException(nameof(depth)); } if (indent < 0) { throw new ArgumentOutOfRangeException(nameof(indent)); } builder.Append(' ', indent * depth); builder.Append($"{nodeOrToken.Kind()} {nodeOrToken.Span}"); builder.AppendLine(); foreach (SyntaxTrivia trivia in nodeOrToken.GetLeadingTrivia()) { builder.Append(' ', indent * (depth + 1)); builder.Append($"Lead: {trivia.Kind()} {trivia.Span}"); builder.AppendLine(); } foreach (SyntaxTrivia trivia in nodeOrToken.GetTrailingTrivia()) { builder.Append(' ', indent * (depth + 1)); builder.Append($"Trail: {trivia.Kind()} {trivia.Span}"); builder.AppendLine(); } foreach (SyntaxNodeOrToken childNodeOrToken in nodeOrToken.ChildNodesAndTokens()) { PrintSyntaxNodeOrToken(builder, childNodeOrToken, depth + 1, indent); } }
private Nodes SyntaxNodeToNodes(SyntaxNodeOrToken s) { Nodes node = new Nodes(); node.Kind = s.Kind(); node.Language = s.Kind().ToString() + " [" + s.SpanStart + "..." + s.Span.End + "]"; node.syntaxNode = s; if (s.HasLeadingTrivia) { SyntaxTriviaList d = s.GetLeadingTrivia(); foreach (SyntaxTrivia t in d) { Nodes tr = new Nodes(); tr.Language = "Leading: " + t.ToString() + " [" + t.SpanStart + "..." + t.Span.End + "]"; node.nodes.Add(tr); } node.IsLeadingTrivia = true; } if (s.HasTrailingTrivia) { SyntaxTriviaList d = s.GetTrailingTrivia(); foreach (SyntaxTrivia t in d) { Nodes tr = new Nodes(); tr.Language = "Trailing: " + t.ToString() + " [" + t.SpanStart + "..." + t.Span.End + "]"; node.nodes.Add(tr); } node.IsTrailingTrivia = true; } foreach (SyntaxNodeOrToken c in s.ChildNodesAndTokens()) { Nodes ng = SyntaxNodeToNodes(c); node.nodes.Add(ng); } return(node); }
private void WalkTreeAndVerify(SyntaxNodeOrToken incNode, SyntaxNodeOrToken fullNode) { var incChildren = incNode.ChildNodesAndTokens(); var fullChildren = fullNode.ChildNodesAndTokens(); Assert.Equal(incChildren.Count, fullChildren.Count); for (int i = 0; i < incChildren.Count; i++) { var incChild = incChildren[i]; var fullChild = fullChildren[i]; WalkTreeAndVerify(incChild, fullChild); } }
void UpdateWordAdornments() { SnapshotPoint currentRequest = RequestedPoint; var document = View.TextSnapshot.TextBuffer.GetRelatedDocuments().FirstOrDefault(); if (document == null) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } var syntaxTree = document.GetSyntaxTreeAsync().ConfigureAwait(false).GetAwaiter().GetResult(); var root = syntaxTree.GetRoot(); SyntaxNodeOrToken token = root.FindToken(currentRequest.Position); var line = View.TextSnapshot.GetLineFromPosition(currentRequest.Position); SyntaxNodeOrToken lineSyntax = root.FindNode(TextSpan.FromBounds(line.Start, line.End)); var nodes = lineSyntax.ChildNodesAndTokens(); var methods = new List <SyntaxNodeOrToken>(); TraversideNodes(nodes, methods); if (!methods.Any()) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } var idx = -1; TextSpan currentArgSpan = TextSpan.FromBounds(0, 0); SyntaxNodeOrToken _sqlSyntax = null; foreach (var method in methods) { var _argsSyntax = ((SyntaxNodeOrToken)method.Parent).GetNextSibling().ChildNodesAndTokens().Where(p => p.IsKind(SyntaxKind.Argument)); foreach (var _arg in _argsSyntax) { idx++; if (_arg.Span.Start <= currentRequest.Position && currentRequest.Position <= _arg.Span.End) { currentArgSpan = _arg.Span; var dot = method.GetPreviousSibling(); //如果方法名签名不是一个点(.),终止 if (!dot.IsKind(SyntaxKind.DotToken)) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } _sqlSyntax = dot.GetPreviousSibling(); break; } } } //如果没有选择参数,并且Splice方法前不是字符串 if (idx == -1 || !_sqlSyntax.IsKind(SyntaxKind.StringLiteralExpression)) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } //SyntaxNodeOrToken argsSyntax = null; //if (token.Parent.IsKind(SyntaxKind.ArgumentList)) // argsSyntax = token.Parent; //else // argsSyntax = ((SyntaxNodeOrToken)token.Parent?.Parent).GetPreviousSibling().Parent;//此情况是光标在具体某个参数上 //if (argsSyntax.RawKind == 0) // argsSyntax = ((SyntaxNodeOrToken)token.Parent?.Parent?.Parent).GetPreviousSibling().Parent; //if (argsSyntax == null || !argsSyntax.IsKind(SyntaxKind.ArgumentList)) //{ // SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); // return; //} //var expression = argsSyntax.GetPreviousSibling(); //#region 判断是不是拼接sql的方法(Splice) //var syntax = expression.ChildNodesAndTokens(); //if (syntax.Count != 3) //{ // SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); // return; //} //if (!syntax.First().IsKind(SyntaxKind.StringLiteralExpression) || !syntax.Last().IsKind(SyntaxKind.IdentifierName) || !syntax.Last().ToFullString().Equals("Splice", StringComparison.Ordinal)) //{ // SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); // return; //} //#endregion //var args = argsSyntax.ChildNodesAndTokens().Where(p => p.IsKind(SyntaxKind.Argument)).ToList(); //var pointer = token.Span.Start; ////获取当前焦点在第几个参数 //foreach (var arg in args) //{ // idx++; // if (arg.Span.Start >= pointer && pointer <= arg.Span.End) // break; //} //var sqlSyntax = syntax.First(); var sql = _sqlSyntax.ToString(); var startIdx = -1; var endIdx = -1; var currentIdx = 0; for (var i = 0; i <= idx; i++) { startIdx = sql.IndexOf("{", currentIdx); if (startIdx == -1) { break; } endIdx = sql.IndexOf("}", startIdx); if (endIdx == -1) { break; } currentIdx = endIdx; } if (startIdx == -1 || endIdx == -1) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(), null); return; } List <SnapshotSpan> wordSpans = new List <SnapshotSpan>(); //添加当前选中的参数高亮 //wordSpans.Add(new SnapshotSpan(View.TextSnapshot, currentArgSpan.Start, currentArgSpan.End - currentArgSpan.Start)); //添加对应的拼接sql部分高亮 wordSpans.Add(new SnapshotSpan(View.TextSnapshot, _sqlSyntax.Span.Start + startIdx, endIdx - startIdx + 1)); //Find all words in the buffer like the one the caret is on TextExtent word = TextStructureNavigator.GetExtentOfWord(currentRequest); SnapshotSpan currentWord = word.Span; //If this is the current word, and the caret moved within a word, we're done. if (CurrentWord.HasValue && currentWord == CurrentWord) { return; } //If another change hasn't happened, do a real update if (currentRequest == RequestedPoint) { SynchronousUpdate(currentRequest, new NormalizedSnapshotSpanCollection(wordSpans), currentWord); } }
internal Roslyn.Compilers.CSharp.SyntaxToken FindTokenInternal(int position) { SyntaxNodeOrToken syntaxNodeOrToken = (SyntaxNodeOrToken)this; while (syntaxNodeOrToken.AsNode() != null) { syntaxNodeOrToken = Roslyn.Compilers.CSharp.SyntaxNode.GetChildThatContainsPosition(syntaxNodeOrToken.ChildNodesAndTokens(), position); } return(syntaxNodeOrToken.AsToken()); }
private void TreeToString(SyntaxNodeOrToken syntaxNodeOrToken, string indent, CodeFixValidationMode validationMode, StringBuilder result) { if (syntaxNodeOrToken.IsNode) { result.AppendLine($"{indent}Node({Kind(syntaxNodeOrToken.RawKind)}):"); var childIndent = indent + " "; foreach (var child in syntaxNodeOrToken.ChildNodesAndTokens()) { TreeToString(child, childIndent, validationMode, result); } } else { var syntaxToken = syntaxNodeOrToken.AsToken(); result.AppendLine($"{indent}Token({Kind(syntaxToken.RawKind)}): {Escape(syntaxToken.Text)}"); if (validationMode == CodeFixValidationMode.Full) { var childIndent = indent + " "; foreach (var trivia in syntaxToken.LeadingTrivia) { if (trivia.HasStructure) { result.AppendLine($"{childIndent}Leading({Kind(trivia.RawKind)}):"); TreeToString(trivia.GetStructure(), childIndent + " ", validationMode, result); } else { result.AppendLine($"{childIndent}Leading({Kind(trivia.RawKind)}): {Escape(trivia.ToString())}"); } } foreach (var trivia in syntaxToken.TrailingTrivia) { if (trivia.HasStructure) { result.AppendLine($"{childIndent}Trailing({Kind(trivia.RawKind)}):"); TreeToString(trivia.GetStructure(), childIndent + " ", validationMode, result); } else { result.AppendLine($"{childIndent}Trailing({Kind(trivia.RawKind)}): {Escape(trivia.ToString())}"); } } } } // Local functions string Escape(string text) { return(text .Replace("\\", "\\\\") .Replace("\t", "\\t") .Replace("\r", "\\r") .Replace("\n", "\\n")); } string Kind(int syntaxKind) { if (SyntaxKindType.GetTypeInfo()?.IsEnum ?? false) { return(Enum.Format(SyntaxKindType, (ushort)syntaxKind, "G")); } else { return(syntaxKind.ToString()); } } }
private static void CompareTreeEquivalence(SyntaxNodeOrToken parsedTreeNode, SyntaxNodeOrToken incrementalTreeNode) { Assert.Equal(parsedTreeNode.Kind(), incrementalTreeNode.Kind()); Assert.Equal(parsedTreeNode.ChildNodesAndTokens().Count, incrementalTreeNode.ChildNodesAndTokens().Count); for (int i = 0; i < parsedTreeNode.ChildNodesAndTokens().Count; i++) { CompareTreeEquivalence(parsedTreeNode.ChildNodesAndTokens()[i], incrementalTreeNode.ChildNodesAndTokens()[i]); } }
private int GetSimilarity(SyntaxNodeOrToken node1, SyntaxNodeOrToken node2) { // count the characters in the common/identical nodes int w = 0; _nodeSimilaritySet.Clear(); _tokenTextSimilaritySet.Clear(); if (node1.IsToken && node2.IsToken) { var text1 = node1.ToString(); var text2 = node2.ToString(); if (text1 == text2) { // main text of token is the same w += text1.Length; } foreach (var tr in node1.GetLeadingTrivia()) { _nodeSimilaritySet.Add(tr.UnderlyingNode); } foreach (var tr in node1.GetTrailingTrivia()) { _nodeSimilaritySet.Add(tr.UnderlyingNode); } foreach (var tr in node2.GetLeadingTrivia()) { if (_nodeSimilaritySet.Contains(tr.UnderlyingNode)) { w += tr.FullSpan.Length; } } foreach (var tr in node2.GetTrailingTrivia()) { if (_nodeSimilaritySet.Contains(tr.UnderlyingNode)) { w += tr.FullSpan.Length; } } } else { foreach (var n1 in node1.ChildNodesAndTokens()) { _nodeSimilaritySet.Add(n1.UnderlyingNode); if (n1.IsToken) { _tokenTextSimilaritySet.Add(n1.ToString()); } } foreach (var n2 in node2.ChildNodesAndTokens()) { if (_nodeSimilaritySet.Contains(n2.UnderlyingNode)) { w += n2.FullSpan.Length; } else if (n2.IsToken) { var tokenText = n2.ToString(); if (_tokenTextSimilaritySet.Contains(tokenText)) { w += tokenText.Length; } } } } return w; }
private static int GetDepth(SyntaxNodeOrToken syntax, int depth = 0) { if (syntax.IsNode) { return syntax.ChildNodesAndTokens().Count == 0 ? depth : syntax.ChildNodesAndTokens().Max(x => GetDepth(x, depth + 1)); } return (syntax.AsToken().HasLeadingTrivia || syntax.AsToken().HasTrailingTrivia) ? depth + 1 : depth; }