public ParseData() { TreeStructureChanged = true; _parseCompleteEventArg = null; NotificationPending = false; _lastVersion = -1; }
public bool Update(DocumentParseCompleteEventArgs e) { int versionNumber = (e.SourceChange.NewBuffer as IShimTextBuffer).Snapshot.Version.VersionNumber; if (versionNumber >= _lastVersion) { _lastVersion = versionNumber; _parseCompleteEventArg = e; } if (e.TreeStructureChanged) { TreeStructureChanged = true; } else if (!TreeStructureChanged) { TextChange sourceChange = e.SourceChange; if (sourceChange.NewLength > 1) { if ((sourceChange.NewBuffer as IShimTextBuffer).Snapshot.GetText(sourceChange.NewPosition, sourceChange.NewLength).Any(c => char.IsWhiteSpace(c))) { TreeStructureChanged = true; } } } bool expr_BE = !NotificationPending; if (expr_BE) { NotificationPending = true; } return(expr_BE); }
public void CheckForStructureChangesStartsReparseAndFiresDocumentParseCompletedEventIfNoAdditionalChangesQueued() { // Arrange using (RazorEditorParser parser = CreateClientParser()) { StringTextBuffer input = new StringTextBuffer(SimpleCSHTMLDocument.ReadAllText()); DocumentParseCompleteEventArgs capturedArgs = null; ManualResetEventSlim parseComplete = new ManualResetEventSlim(false); parser.DocumentParseComplete += (sender, args) => { capturedArgs = args; parseComplete.Set(); }; // Act parser.CheckForStructureChanges(new TextChange(0, 0, new StringTextBuffer(String.Empty), input.Length, input)); // Assert MiscUtils.DoWithTimeoutIfNotDebugging(parseComplete.Wait); string generatedCode = capturedArgs.GeneratorResults.GeneratedCode.GenerateCode <CSharpCodeProvider>(); Assert.Equal( SimpleCSHTMLDocumentGenerated.ReadAllText(), MiscUtils.StripRuntimeVersion(generatedCode)); } }
protected virtual void OnResultsReady(DocumentParseCompleteEventArgs args) { var handler = ResultsReady; if (handler != null) { handler(this, args); } }
public void OnDocumentParseComplete(object sender, DocumentParseCompleteEventArgs args) { EventHandler <DocumentParseCompleteEventArgs> documentParseComplete = DocumentParseComplete; if (documentParseComplete != null) { documentParseComplete(this, args); } }
void CreateParserFor(string fileName) { editorParser = new RazorEditorParserFixed.RazorEditorParser(CreateRazorHost(fileName), fileName); parseComplete = new AutoResetEvent(false); editorParser.DocumentParseComplete += (sender, args) => { capturedArgs = args; parseComplete.Set(); }; lastParsedFile = fileName; }
private void DocumentParseComplete(object sender, DocumentParseCompleteEventArgs e) { if (_parseData == null) { return; } ParseData parseData = _parseData; bool flag2; lock (parseData) { flag2 = _parseData.Update(e); } if (flag2) { WebEditor.DispatchOnUIThread(delegate { DocumentParseCompleteMainThread(); }); } }
private void OnDocumentParseComplete(DocumentParseCompleteEventArgs args) { using (_parser.SynchronizeMainThreadState()) { _currentParseTree = args.GeneratorResults.Document; _lastChangeOwner = null; } Debug.Assert(args != null, "Event arguments cannot be null"); EventHandler <DocumentParseCompleteEventArgs> handler = DocumentParseComplete; if (handler != null) { try { handler(this, args); } catch (Exception ex) { Debug.WriteLine("[RzEd] Document Parse Complete Handler Threw: " + ex.ToString()); } } }
public void ReturnParcel(DocumentParseCompleteEventArgs args) { lock (_stateLock) { // Clear the current parcel cancellation source if (_currentParcelCancelSource != null) { _currentParcelCancelSource.Dispose(); _currentParcelCancelSource = null; } // If there are things waiting to be parsed, just don't fire the event because we're already out of date if (_changes.Any()) { return; } } var handler = ResultsReady; if (handler != null) { handler(this, args); } }
// **** BACKGROUND THREAD **** private void WorkerLoop() { long? elapsedMs = null; string fileNameOnly = Path.GetFileName(_fileName); #if EDITOR_TRACING Stopwatch sw = new Stopwatch(); #endif try { RazorEditorTrace.TraceLine(RazorResources.Trace_BackgroundThreadStart, fileNameOnly); EnsureOnThread(); while (!_shutdownToken.IsCancellationRequested) { // Grab the parcel of work to do WorkParcel parcel = _main.GetParcel(); if (parcel.Changes.Any()) { RazorEditorTrace.TraceLine(RazorResources.Trace_ChangesArrived, fileNameOnly, parcel.Changes.Count); try { DocumentParseCompleteEventArgs args = null; using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken)) { if (parcel != null && !linkedCancel.IsCancellationRequested) { // Collect ALL changes #if EDITOR_TRACING if (_previouslyDiscarded != null && _previouslyDiscarded.Any()) { RazorEditorTrace.TraceLine(RazorResources.Trace_CollectedDiscardedChanges, fileNameOnly, _previouslyDiscarded.Count); } #endif var allChanges = Enumerable.Concat( _previouslyDiscarded ?? Enumerable.Empty <TextChange>(), parcel.Changes).ToList(); var finalChange = allChanges.LastOrDefault(); if (finalChange != default(TextChange)) { #if EDITOR_TRACING sw.Start(); #endif GeneratorResults results = ParseChange(finalChange.NewBuffer, linkedCancel.Token); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif RazorEditorTrace.TraceLine( RazorResources.Trace_ParseComplete, fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString() : "?"); if (results != null && !linkedCancel.IsCancellationRequested) { // Clear discarded changes list _previouslyDiscarded = null; // Take the current tree and check for differences #if EDITOR_TRACING sw.Start(); #endif bool treeStructureChanged = _currentParseTree == null || TreesAreDifferent(_currentParseTree, results.Document, allChanges, parcel.CancelToken); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif _currentParseTree = results.Document; RazorEditorTrace.TraceLine(RazorResources.Trace_TreesCompared, fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString() : "?", treeStructureChanged); // Build Arguments args = new DocumentParseCompleteEventArgs() { GeneratorResults = results, SourceChange = finalChange, TreeStructureChanged = treeStructureChanged }; } else { // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set RazorEditorTrace.TraceLine(RazorResources.Trace_ChangesDiscarded, fileNameOnly, allChanges.Count); _previouslyDiscarded = allChanges; } #if CHECK_TREE if (args != null) { // Rewind the buffer and sanity check the line mappings finalChange.NewBuffer.Position = 0; int lineCount = finalChange.NewBuffer.ReadToEnd().Split(new string[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.None).Count(); Debug.Assert( !args.GeneratorResults.DesignTimeLineMappings.Any(pair => pair.Value.StartLine > lineCount), "Found a design-time line mapping referring to a line outside the source file!"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.LineIndex > lineCount), "Found a span with a line number outside the source file"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.AbsoluteIndex > parcel.NewBuffer.Length), "Found a span with an absolute offset outside the source file"); } #endif } } } if (args != null) { _main.ReturnParcel(args); } } catch (OperationCanceledException) { } } else { RazorEditorTrace.TraceLine(RazorResources.Trace_NoChangesArrived, fileNameOnly, parcel.Changes.Count); Thread.Yield(); } } } catch (OperationCanceledException) { // Do nothing. Just shut down. } catch (Exception ex) { MonoDevelop.Core.LoggingService.LogInternalError("Internal error in Razor parser", ex); } finally { RazorEditorTrace.TraceLine(RazorResources.Trace_BackgroundThreadShutdown, fileNameOnly); // Clean up main thread resources _main.Dispose(); } }
// **** BACKGROUND THREAD **** private void WorkerLoop() { long?elapsedMs = null; var fileNameOnly = Path.GetFileName(_fileName); #if EDITOR_TRACING var sw = new Stopwatch(); #endif try { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadStart(fileNameOnly)); EnsureOnThread(); #if NETSTANDARD1_3 var spinWait = new SpinWait(); #endif while (!_shutdownToken.IsCancellationRequested) { // Grab the parcel of work to do var parcel = _main.GetParcel(); if (parcel.Changes.Any()) { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesArrived(fileNameOnly, parcel.Changes.Count)); try { DocumentParseCompleteEventArgs args = null; using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken)) { if (!linkedCancel.IsCancellationRequested) { // Collect ALL changes #if EDITOR_TRACING if (_previouslyDiscarded != null && _previouslyDiscarded.Any()) { RazorEditorTrace.TraceLine(RazorResources.Trace_CollectedDiscardedChanges, fileNameOnly, _previouslyDiscarded.Count); } #endif List <TextChange> allChanges; if (_previouslyDiscarded != null) { allChanges = Enumerable.Concat(_previouslyDiscarded, parcel.Changes).ToList(); } else { allChanges = parcel.Changes.ToList(); } var finalChange = allChanges.Last(); #if EDITOR_TRACING sw.Start(); #endif var results = ParseChange(finalChange.NewBuffer, linkedCancel.Token); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif RazorEditorTrace.TraceLine( RazorResources.FormatTrace_ParseComplete( fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?")); if (results != null && !linkedCancel.IsCancellationRequested) { // Clear discarded changes list _previouslyDiscarded = null; // Take the current tree and check for differences #if EDITOR_TRACING sw.Start(); #endif var treeStructureChanged = _currentParseTree == null || TreesAreDifferent(_currentParseTree, results.Document, allChanges, parcel.CancelToken); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif _currentParseTree = results.Document; RazorEditorTrace.TraceLine(RazorResources.FormatTrace_TreesCompared( fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?", treeStructureChanged)); // Build Arguments args = new DocumentParseCompleteEventArgs() { GeneratorResults = results, SourceChange = finalChange, TreeStructureChanged = treeStructureChanged }; } else { // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesDiscarded(fileNameOnly, allChanges.Count)); _previouslyDiscarded = allChanges; } #if CHECK_TREE if (args != null) { // Rewind the buffer and sanity check the line mappings finalChange.NewBuffer.Position = 0; var lineCount = finalChange.NewBuffer.ReadToEnd().Split(new string[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.None).Count(); Debug.Assert( !args.GeneratorResults.DesignTimeLineMappings.Any(pair => pair.Value.StartLine > lineCount), "Found a design-time line mapping referring to a line outside the source file!"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.LineIndex > lineCount), "Found a span with a line number outside the source file"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.AbsoluteIndex > parcel.NewBuffer.Length), "Found a span with an absolute offset outside the source file"); } #endif } } if (args != null) { _main.ReturnParcel(args); } } catch (OperationCanceledException) { } } else { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_NoChangesArrived(fileNameOnly)); #if NETSTANDARD1_3 // This does the equivalent of thread.yield under the covers. spinWait.SpinOnce(); #else // No Yield in CoreCLR Thread.Yield(); #endif } } } catch (OperationCanceledException) { // Do nothing. Just shut down. } finally { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadShutdown(fileNameOnly)); // Clean up main thread resources _main.Dispose(); } }
private void OnDocumentParseComplete(DocumentParseCompleteEventArgs args) { using (_parser.SynchronizeMainThreadState()) { _currentParseTree = args.GeneratorResults.Document; _lastChangeOwner = null; } Debug.Assert(args != null, "Event arguments cannot be null"); EventHandler<DocumentParseCompleteEventArgs> handler = DocumentParseComplete; if (handler != null) { try { handler(this, args); } catch (Exception ex) { Debug.WriteLine("[RzEd] Document Parse Complete Handler Threw: " + ex.ToString()); } } }
// **** BACKGROUND THREAD **** private void WorkerLoop() { var fileNameOnly = Path.GetFileName(_filePath); try { EnsureOnThread(); while (!_shutdownToken.IsCancellationRequested) { // Grab the parcel of work to do var parcel = _main.GetParcel(); if (parcel.Edits.Any()) { try { DocumentParseCompleteEventArgs args = null; using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken)) { if (!linkedCancel.IsCancellationRequested) { // Collect ALL changes List <Edit> allEdits; if (_previouslyDiscarded != null) { allEdits = Enumerable.Concat(_previouslyDiscarded, parcel.Edits).ToList(); } else { allEdits = parcel.Edits.ToList(); } var finalEdit = allEdits.Last(); var results = ParseChange(finalEdit.Snapshot, linkedCancel.Token); if (results != null && !linkedCancel.IsCancellationRequested) { // Clear discarded changes list _previouslyDiscarded = null; var treeStructureChanged = _currentSyntaxTree == null || TreesAreDifferent(_currentSyntaxTree, results.GetSyntaxTree(), allEdits, parcel.CancelToken); _currentSyntaxTree = results.GetSyntaxTree(); // Build Arguments args = new DocumentParseCompleteEventArgs( finalEdit.Change, finalEdit.Snapshot, treeStructureChanged, results); } else { // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set _previouslyDiscarded = allEdits; } } } if (args != null) { _main.ReturnParcel(args); } } catch (OperationCanceledException) { } } else { Thread.Yield(); } } } catch (OperationCanceledException) { // Do nothing. Just shut down. } finally { // Clean up main thread resources _main.Dispose(); } }
// **** BACKGROUND THREAD **** private void WorkerLoop() { long? elapsedMs = null; string fileNameOnly = Path.GetFileName(_fileName); #if EDITOR_TRACING Stopwatch sw = new Stopwatch(); #endif try { RazorEditorTrace.TraceLine("[BG][{0}] Startup", fileNameOnly); EnsureOnThread(); while (!_shutdownToken.IsCancellationRequested) { // Grab the parcel of work to do WorkParcel parcel = _main.GetParcel(); if (parcel.Changes.Any()) { RazorEditorTrace.TraceLine("[BG][{0}] {1} changes arrived", fileNameOnly, parcel.Changes.Count); try { DocumentParseCompleteEventArgs args = null; using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken)) { if (parcel != null && !linkedCancel.IsCancellationRequested) { // Collect ALL changes #if EDITOR_TRACING if (_previouslyDiscarded != null && _previouslyDiscarded.Any()) { RazorEditorTrace.TraceLine("[BG][{0}] Collecting {1} discarded changes", fileNameOnly, _previouslyDiscarded.Count); } #endif var allChanges = Enumerable.Concat( _previouslyDiscarded ?? Enumerable.Empty<TextChange>(), parcel.Changes).ToList(); var finalChange = allChanges.LastOrDefault(); if (finalChange != null) { #if EDITOR_TRACING sw.Start(); #endif GeneratorResults results = ParseChange(finalChange.NewBuffer, linkedCancel.Token); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif RazorEditorTrace.TraceLine( "[BG][{0}] Parse Complete in {1}ms", fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString() : "?"); if (results != null && !linkedCancel.IsCancellationRequested) { // Clear discarded changes list _previouslyDiscarded = null; // Take the current tree and check for differences #if EDITOR_TRACING sw.Start(); #endif bool treeStructureChanged = _currentParseTree == null || TreesAreDifferent(_currentParseTree, results.Document, allChanges, parcel.CancelToken); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif _currentParseTree = results.Document; RazorEditorTrace.TraceLine("[BG][{0}] Trees Compared in {1}ms. Different = {2}", fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString() : "?", treeStructureChanged); // Build Arguments args = new DocumentParseCompleteEventArgs() { GeneratorResults = results, SourceChange = finalChange, TreeStructureChanged = treeStructureChanged }; } else { // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set RazorEditorTrace.TraceLine("[BG][{0}] Discarded {1} changes", fileNameOnly, allChanges.Count); _previouslyDiscarded = allChanges; } #if CHECK_TREE if (args != null) { // Rewind the buffer and sanity check the line mappings finalChange.NewBuffer.Position = 0; int lineCount = finalChange.NewBuffer.ReadToEnd().Split(new string[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.None).Count(); Debug.Assert( !args.GeneratorResults.DesignTimeLineMappings.Any(pair => pair.Value.StartLine > lineCount), "Found a design-time line mapping referring to a line outside the source file!"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.LineIndex > lineCount), "Found a span with a line number outside the source file"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.AbsoluteIndex > parcel.NewBuffer.Length), "Found a span with an absolute offset outside the source file"); } #endif } } } if (args != null) { _main.ReturnParcel(args); } } catch (OperationCanceledException) { } } else { RazorEditorTrace.TraceLine("[BG][{0}] no changes arrived?", fileNameOnly, parcel.Changes.Count); Thread.Yield(); } } } catch (OperationCanceledException) { // Do nothing. Just shut down. } finally { RazorEditorTrace.TraceLine("[BG][{0}] Shutdown", fileNameOnly); // Clean up main thread resources _main.Dispose(); } }
// **** BACKGROUND THREAD **** private void WorkerLoop() { long? elapsedMs = null; var fileNameOnly = Path.GetFileName(_fileName); #if EDITOR_TRACING var sw = new Stopwatch(); #endif try { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadStart(fileNameOnly)); EnsureOnThread(); #if DOTNET5_4 var spinWait = new SpinWait(); #endif while (!_shutdownToken.IsCancellationRequested) { // Grab the parcel of work to do var parcel = _main.GetParcel(); if (parcel.Changes.Any()) { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesArrived(fileNameOnly, parcel.Changes.Count)); try { DocumentParseCompleteEventArgs args = null; using (var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(_shutdownToken, parcel.CancelToken)) { if (!linkedCancel.IsCancellationRequested) { // Collect ALL changes #if EDITOR_TRACING if (_previouslyDiscarded != null && _previouslyDiscarded.Any()) { RazorEditorTrace.TraceLine(RazorResources.Trace_CollectedDiscardedChanges, fileNameOnly, _previouslyDiscarded.Count); } #endif List<TextChange> allChanges; if (_previouslyDiscarded != null) { allChanges = Enumerable.Concat(_previouslyDiscarded, parcel.Changes).ToList(); } else { allChanges = parcel.Changes.ToList(); } var finalChange = allChanges.Last(); #if EDITOR_TRACING sw.Start(); #endif var results = ParseChange(finalChange.NewBuffer, linkedCancel.Token); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif RazorEditorTrace.TraceLine( RazorResources.FormatTrace_ParseComplete( fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?")); if (results != null && !linkedCancel.IsCancellationRequested) { // Clear discarded changes list _previouslyDiscarded = null; // Take the current tree and check for differences #if EDITOR_TRACING sw.Start(); #endif var treeStructureChanged = _currentParseTree == null || TreesAreDifferent(_currentParseTree, results.Document, allChanges, parcel.CancelToken); #if EDITOR_TRACING sw.Stop(); elapsedMs = sw.ElapsedMilliseconds; sw.Reset(); #endif _currentParseTree = results.Document; RazorEditorTrace.TraceLine(RazorResources.FormatTrace_TreesCompared( fileNameOnly, elapsedMs.HasValue ? elapsedMs.Value.ToString(CultureInfo.InvariantCulture) : "?", treeStructureChanged)); // Build Arguments args = new DocumentParseCompleteEventArgs() { GeneratorResults = results, SourceChange = finalChange, TreeStructureChanged = treeStructureChanged }; } else { // Parse completed but we were cancelled in the mean time. Add these to the discarded changes set RazorEditorTrace.TraceLine(RazorResources.FormatTrace_ChangesDiscarded(fileNameOnly, allChanges.Count)); _previouslyDiscarded = allChanges; } #if CHECK_TREE if (args != null) { // Rewind the buffer and sanity check the line mappings finalChange.NewBuffer.Position = 0; var lineCount = finalChange.NewBuffer.ReadToEnd().Split(new string[] { Environment.NewLine, "\r", "\n" }, StringSplitOptions.None).Count(); Debug.Assert( !args.GeneratorResults.DesignTimeLineMappings.Any(pair => pair.Value.StartLine > lineCount), "Found a design-time line mapping referring to a line outside the source file!"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.LineIndex > lineCount), "Found a span with a line number outside the source file"); Debug.Assert( !args.GeneratorResults.Document.Flatten().Any(span => span.Start.AbsoluteIndex > parcel.NewBuffer.Length), "Found a span with an absolute offset outside the source file"); } #endif } } if (args != null) { _main.ReturnParcel(args); } } catch (OperationCanceledException) { } } else { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_NoChangesArrived(fileNameOnly)); #if DOTNET5_4 // This does the equivalent of thread.yield under the covers. spinWait.SpinOnce(); #else // No Yield in CoreCLR Thread.Yield(); #endif } } } catch (OperationCanceledException) { // Do nothing. Just shut down. } finally { RazorEditorTrace.TraceLine(RazorResources.FormatTrace_BackgroundThreadShutdown(fileNameOnly)); // Clean up main thread resources _main.Dispose(); } }