protected override ClassificationRefresh ProcessText( ITextSnapshot snapshot, Parser parseResult, SharedTagList tagList, bool writeAccess) { bool parsedCorrectly = parseResult.ParsedCorrectly; if (writeAccess) { foreach (var token in parseResult.Tokens) { tagList.AddRange(this, QmlSyntaxTag.GetClassification(snapshot, token)); } foreach (var node in parseResult.AstNodes) { tagList.AddRange(this, QmlSyntaxTag.GetClassification(snapshot, node)); } } if (parsedCorrectly) { return(ClassificationRefresh.FullText); } else { return(ClassificationRefresh.TagsOnly); } }
private void RefreshClassification( ITextSnapshot snapshot, ClassificationRefresh refresh, SharedTagList tagList) { var tagsChangedHandler = TagsChanged; if (refresh == ClassificationRefresh.FullText) { var span = new SnapshotSpan(Buffer.CurrentSnapshot, 0, Buffer.CurrentSnapshot.Length); if (tagsChangedHandler != null) { tagsChangedHandler.Invoke(this, new SnapshotSpanEventArgs(span)); } } else { foreach (var tag in tagList.Values) { var tagMapped = tag.MapToSnapshot(snapshot); if (tagsChangedHandler != null) { tagsChangedHandler.Invoke(this, new SnapshotSpanEventArgs(tagMapped.Span)); } } } }
protected override ClassificationRefresh ProcessText( ITextSnapshot snapshot, Parser parseResult, SharedTagList tagList, bool writeAccess) { if (writeAccess) { var expressions = parseResult.AstNodes .Where(x => x.Kind == AstNodeKind.FieldMemberExpression || x.Kind == AstNodeKind.IdentifierExpression) .GroupBy(x => x.FirstSourceLocation.Offset) .Select(x => new { Offset = x.Key, Length = x.Max(y => y.LastSourceLocation.Offset + y.LastSourceLocation.Length) - x.Key, List = x.OrderBy(y => y.LastSourceLocation.Offset + y.LastSourceLocation.Length) }); tagList.AddRange(this, expressions .Select(x => new ExprTrackingTag(snapshot, x.Offset, x.Length, x.List))); } return(ClassificationRefresh.FullText); }
private void TextView_Closed(object sender, EventArgs e) { if (currentParserKey != null) { ParserStore.Instance.Release(this, currentParserKey); currentParserKey = null; } if (currentTagListKey != null) { TagListStore.Instance.Release(this, currentTagListKey); currentTagListKey = null; } currentTagList = null; }
protected override ClassificationRefresh ProcessText( ITextSnapshot snapshot, Parser parseResult, SharedTagList tagList, bool writeAccess) { if (writeAccess) { foreach (var diag in parseResult.DiagnosticMessages) { tagList.Add(this, new QmlDiagnosticsTag(snapshot, diag)); } } return(ClassificationRefresh.FullText); }
protected QmlAsyncClassifier( string classificationType, ITextView textView, ITextBuffer buffer) { TextView = textView; textView.Closed += TextView_Closed; Buffer = buffer; buffer.Changed += Buffer_Changed; dispatcher = Dispatcher.CurrentDispatcher; timer = new DispatcherTimer(DispatcherPriority.ApplicationIdle, dispatcher) { Interval = TimeSpan.FromMilliseconds(250) }; timer.Tick += Timer_Tick; currentParserKey = null; currentTagListKey = null; currentTagList = null; this.classificationType = classificationType; AsyncParse(buffer.CurrentSnapshot); }
private async void AsyncParse(ITextSnapshot snapshot) { lock (criticalSection) { if (flag) { return; } flag = true; } var newParserKey = new ParserKey(snapshot); var newTagListKey = new TagListKey(classificationType, snapshot); if (newParserKey == currentParserKey || newTagListKey == currentTagListKey) { return; } ParserKey oldParserKey = null; TagListKey oldTagListKey = null; await Task.Run(() => { var parser = ParserStore.Instance.Get(this, newParserKey); var tagList = TagListStore.Instance.Get(this, newTagListKey); var refresh = ClassificationRefresh.FullText; try { var accessType = tagList.RequestWriteAccess(this); refresh = ProcessText(snapshot, parser, tagList, accessType == SharedTagList.AccessType.ReadWrite); } finally { tagList.WriteComplete(this); } oldParserKey = currentParserKey; currentParserKey = newParserKey; oldTagListKey = currentTagListKey; currentTagListKey = newTagListKey; currentTagList = tagList; RefreshClassification(snapshot, refresh, tagList); var currentVersion = Buffer.CurrentSnapshot.Version; if (snapshot.Version.VersionNumber == currentVersion.VersionNumber) { timer.Stop(); } else { timer.Start(); } }); lock (criticalSection) { flag = false; } await Task.Run(() => { if (oldParserKey != null) { ParserStore.Instance.Release(this, oldParserKey); } if (oldTagListKey != null) { TagListStore.Instance.Release(this, oldTagListKey); } }); }
/// <summary> /// Process QML source code. Implementations will override this method with the specific /// processing required to convert the parser results into a list of tracking tags /// </summary> /// <param name="snapshot">The current version of the source code</param> /// <param name="parseResult">The result of parsing the source code</param> /// <param name="tagList">Shared list of tracking tags</param> /// <param name="writeAccess"> /// If true, the instance is required to populate the list of tags; /// otherwise, the instance has read-only access and cannot modify the list. /// </param> /// <returns> /// Hint on how to notify Visual Studio concerning the tags in the list /// FullText: refresh the entire contents of the text editor /// TagsOnly: refresh only the spans pointed to by the tags /// </returns> protected abstract ClassificationRefresh ProcessText( ITextSnapshot snapshot, Parser parseResult, SharedTagList tagList, bool writeAccess);