Esempio n. 1
0
 public ParseData()
 {
     TreeStructureChanged   = true;
     _parseCompleteEventArg = null;
     NotificationPending    = false;
     _lastVersion           = -1;
 }
Esempio n. 2
0
            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);
            }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
 protected virtual void OnResultsReady(DocumentParseCompleteEventArgs args)
 {
     var handler = ResultsReady;
     if (handler != null)
     {
         handler(this, args);
     }
 }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 7
0
        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;
        }
Esempio n. 8
0
        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();
                });
            }
        }
Esempio n. 9
0
        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());
                }
            }
        }
Esempio n. 10
0
            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);
                }
            }
Esempio n. 11
0
            // **** 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();
                }
            }
Esempio n. 12
0
            // **** 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();
                }
            }
Esempio n. 13
0
        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());
                }
            }
        }
Esempio n. 14
0
                // **** 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();
                    }
                }
Esempio n. 15
0
            // **** 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();
                }
            }
Esempio n. 16
0
            // **** 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();
                }
            }
Esempio n. 17
0
            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);
                }
            }