void FindHiddenRegions(ITextSnapshot snapShot, Irony.Parsing.ParseTreeNode root, ref List <Region> regions) { foreach (var child in root.ChildNodes) { Irony.Parsing.Token startToken = null; Irony.Parsing.Token endToken = null; int startOffset = 0; if (child.Term.Name == LuaTerminalNames.TableConstructor) { startToken = child.ChildNodes.First().Token; // '{' symbol endToken = child.ChildNodes.Last().Token; // '}' symbol } else if (child.Term.Name == LuaTerminalNames.FunctionBody) { startToken = child.ChildNodes[2].Token; // ')' symbol endToken = child.ChildNodes[4].Token; // 'end' keyword //Offset the outline by 1 so we don't hide the ')' symbol. startOffset = 1; } ////折叠连续的多个注释块 //else if (child.Token != null && child.Comments != null) //{ // if (child.Comments.Count > 1) // { // startToken = child.Comments[0]; // endToken = child.Comments.Last(); // startOffset = startToken.Text.Length; // } //} if (startToken != null && endToken != null) { if (startToken.Location.Line != endToken.Location.Line) { //So the column field of Location isn't always accurate... //Position and Line are accurate though.. var startLine = snapShot.GetLineFromLineNumber(startToken.Location.Line); var startLineOffset = startToken.Location.Position - startLine.Start.Position; var endLine = snapShot.GetLineFromLineNumber(endToken.Location.Line); var endLineOffset = (endToken.Location.Position + endToken.Length) - endLine.Start.Position; var region = new Region(); region.StartLine = startToken.Location.Line; region.StartOffset = startLineOffset + startOffset; region.EndLine = endToken.Location.Line; region.EndOffset = endLineOffset; regions.Add(region); } } FindHiddenRegions(snapShot, child, ref regions); } }
// Extension to convert an Irony token to one independent of that library. public static Pie.Expressions.Token Convert(this Irony.Parsing.Token ironyToken) { if (ironyToken == null) { return(null); } var t = new Pie.Expressions.Token(); t.Column = ironyToken.Location.Column; t.Line = ironyToken.Location.Line; t.Position = ironyToken.Location.Position; return(t); }
private bool TryGetTag(Irony.Parsing.Token token, out ClassificationTag tag) { if (token.EditorInfo.Type == Irony.Parsing.TokenType.Identifier) { if (Help.Instance.ContainFunction(token.Text)) { tag = _funcionTag; return(true); } if (Help.Instance.ContainTable(token.Text)) { tag = _tableTag; return(true); } Help.Instance.AddIdentifier(token.Text); } return(_luaTags.TryGetValue(token.EditorInfo.Type, out tag)); }
bool IScanner.ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo, ref int state) { Irony.Parsing.Token token = parser.Scanner.VsReadToken(ref state); // !EOL and !EOF if (token != null && token.Terminal != grammar.Eof && token.Category != Irony.Parsing.TokenCategory.Error) { tokenInfo.StartIndex = token.Location.Position; tokenInfo.EndIndex = tokenInfo.StartIndex + token.Length - 1; Debug.WriteLine("token: '" + token.Text + "'"); if (token.EditorInfo != null) { tokenInfo.Color = (Microsoft.VisualStudio.Package.TokenColor)token.EditorInfo.Color; tokenInfo.Type = (Microsoft.VisualStudio.Package.TokenType)token.EditorInfo.Type; if (token.KeyTerm != null) { tokenInfo.Trigger = (Microsoft.VisualStudio.Package.TokenTriggers)token.KeyTerm.EditorInfo.Triggers; } else { tokenInfo.Trigger = (Microsoft.VisualStudio.Package.TokenTriggers)token.EditorInfo.Triggers; } } else { tokenInfo.Color = TokenColor.Text; tokenInfo.Type = TokenType.Text; } return(true); } return(false); }
public static SnapshotSpan AsSnapshotSpan(this Irony.Parsing.Token token, ITextSnapshot snapshot) { return(new SnapshotSpan(snapshot, token.Location.Position, Math.Max(token.Length, 1))); }
/// <summary> /// 匹配自定义折叠标签,类似 --region [title] 和--endregion之间的内容; /// 匹配多行注释,类似--[[ content --]] /// </summary> /// <param name="root"></param> /// <param name="regions"></param> void FindUserRegions(ITextSnapshot snapShot, Irony.Parsing.ParseTree tree, ref List <Region> regions) { Irony.Parsing.Token startRegion = null; foreach (var token in tree.Tokens) { Region region = null; if (token.Category == Irony.Parsing.TokenCategory.Comment) { if (token.Text.Contains('\n'))//多行注释,折叠 { region = new Region(); region.StartLine = token.Location.Line; region.StartOffset = 0; region.EndLine = token.Location.Line + token.Text.Count(c => { return(c == '\n'); }); region.EndOffset = snapShot.GetLineFromLineNumber(region.EndLine).Length; region.Preview = snapShot.GetLineFromLineNumber(region.StartLine).GetText().Replace("--[[", ""); region.IsCollapsed = true; } else { if (token.Text.StartsWith("--region ") && startRegion == null) { startRegion = token; } else if (token.Text.StartsWith("--endregion") && startRegion != null) { try { region = new Region(); var startLine = snapShot.GetLineFromLineNumber(startRegion.Location.Line); var startLineOffset = startRegion.Location.Position - startLine.Start.Position; var endLine = snapShot.GetLineFromLineNumber(token.Location.Line); var endLineOffset = (token.Location.Position + token.Length) - endLine.Start.Position; region.StartLine = startRegion.Location.Line; region.StartOffset = startLineOffset; region.EndLine = token.Location.Line; region.EndOffset = endLineOffset; region.Preview = startRegion.Text.Replace("--region ", ""); startRegion = null; } catch { StringBuilder sb = new StringBuilder(); sb.AppendLine("LuaOutline.FindUserRegions cause an exception."); sb.AppendLine("Args:"); sb.AppendLine("StartLine:" + startRegion.Location.Line + "," + startRegion.Location.Column); sb.AppendLine("EndLine:" + token.Location.Line + "," + token.Location.Column); sb.AppendLine("TextSnapshot Line:" + snapShot.LineCount); Package.BabePackage.Setting.LogError(sb.ToString()); return; } } } if (region != null) { regions.Add(region); } } } }
public static ClassificationTag GetTag(Irony.Parsing.Token token) { ClassificationTag tag = null; if (token.EditorInfo.Type == Irony.Parsing.TokenType.Identifier) { if (C != null && C.Contains(token.Text)) { tag = CTag; } else if (LuaFramework != null && LuaFramework.Contains(token.Text)) { tag = LuaFrameworkTag; } else if (UserTags != null) { for (int i = 0; i < UserTags.Count; i++) { if (Users[i].Contains(token.Text)) { tag = UserTags[i]; } } } if (m_table != null) { var mem = m_table.Members.Find((lm) => { return(lm is LuaFunction && lm.Name == token.Text); }); if (mem != null) { m_table = null; m_clear = false; if (tag == null) { tag = LuaFunctionTag; } } else if (m_clear == true) { m_table = null; m_clear = false; } else { m_clear = true; } } else if (IntellisenseHelper.ContainsFunction(token.Text)) { if (tag == null) { tag = LuaFunctionTag; } } else if ((m_table = IntellisenseHelper.GetTable(token.Text)) != null) { if (tag == null) { tag = LuaTableTag; } } } if (OtherTags.ContainsKey(token.EditorInfo.Type) && tag == null) { tag = OtherTags[token.EditorInfo.Type]; } return(tag); }
/// <summary> /// In the context of a classification tagger, this is called initially w/ spans for all /// content in the file. /// It is called immediately after the user modifies text given the span of text that was modified. /// It is also called for all lines that are newly visible due to scrolling. /// This function gets called ALOT. Keep processing times to a minimal and try to only handle 1 line at a /// time. /// </summary> /// <param name="spans"></param> /// <returns></returns> public IEnumerable <ITagSpan <ClassificationTag> > GetTags(NormalizedSnapshotSpanCollection spans) { if (spans.Count == 0) { yield break; } var snapShot = spans[0].Snapshot; foreach (var span in spans) { var startLine = span.Start.GetContainingLine(); var endLine = span.End.GetContainingLine(); var startLineNumber = startLine.LineNumber; var endLineNumber = endLine.LineNumber; for (int i = startLineNumber; i <= endLineNumber; i++) { var line = spans[0].Snapshot.GetLineFromLineNumber(i); _parser.Scanner.VsSetSource(line.GetText(), 0); int state = 0; _lineStates.TryGetValue(i, out state); Irony.Parsing.Token token = _parser.Scanner.VsReadToken(ref state); while (token != null) { if (token.Category == Irony.Parsing.TokenCategory.Content) { if (token.EditorInfo != null) { ClassificationTag tag; if (TryGetTag(token, out tag)) { var location = new SnapshotSpan(snapShot, line.Start.Position + token.Location.Position, token.Length); yield return(new TagSpan <ClassificationTag>(location, tag)); } } } else if (token.Category == Irony.Parsing.TokenCategory.Comment) { var location = new SnapshotSpan(snapShot, line.Start.Position + token.Location.Position, token.Length); yield return(new TagSpan <ClassificationTag>(location, _commentTag)); } token = _parser.Scanner.VsReadToken(ref state); } int oldState = 0; _lineStates.TryGetValue(i + 1, out oldState); _lineStates[i + 1] = state; //We're going into overtime, process new tags and send the event that these spans need updating! if (oldState != state) { var lineNumber = endLineNumber; while (oldState != state && lineNumber < snapShot.LineCount) { lineNumber++; var dummyToken = _parser.Scanner.VsReadToken(ref state); while (dummyToken != null) { dummyToken = _parser.Scanner.VsReadToken(ref state); } _lineStates.TryGetValue(lineNumber + 1, out oldState); _lineStates[lineNumber + 1] = state; } if (lineNumber >= snapShot.LineCount) { lineNumber = snapShot.LineCount - 1; } var lastLine = snapShot.GetLineFromLineNumber(lineNumber); if (lastLine != null && this.TagsChanged != null) { int length = lastLine.End.Position - endLine.End.Position; var snapShotSpan = new SnapshotSpan(snapShot, endLine.End.Position, length); this.TagsChanged(this, new SnapshotSpanEventArgs(snapShotSpan)); } } } } }