NotifyTextChange() private method

private NotifyTextChange ( int start, int oldLength, int newLength ) : void
start int
oldLength int
newLength int
return void
Example #1
0
        /// <summary>
        /// Handles non-trivial changes like changes that delete elements,
        /// change identifier names, introducing new braces: changes
        /// that cannot be handled without background parse.
        /// </summary>
        private void ProcessComplexChange(TextChangeContext context)
        {
            // Cancel background parse if it is running
            Cancel();

            TextChange textChange = new TextChange()
            {
                OldTextProvider = context.OldTextProvider,
                NewTextProvider = context.NewTextProvider
            };

            try {
                // Get write lock since there may be concurrent readers
                // of the tree. Note that there are no concurrent writers
                // since changes can only come from a background parser
                // and are always applied from the main thread.
                _editorTree.AcquireWriteLock();

                if (_pendingChanges.FullParseRequired)
                {
                    // When full parse is required, change is like replace the entire file
                    textChange.OldRange = TextRange.FromBounds(0, context.OldText.Length);
                    textChange.NewRange = TextRange.FromBounds(0, context.NewText.Length);

                    // Remove damaged elements if any and reflect text change.
                    // Although we are invalidating the AST next, old copy will
                    // be kept for operations that may need it such as smart indent.
                    bool elementsChanged;
                    _editorTree.InvalidateInRange(_editorTree.AstRoot, context.OldRange, out elementsChanged);
                    _editorTree.NotifyTextChange(context.NewStart, context.OldLength, context.NewLength);
                    // Invalidate will store existing AST as previous snapshot
                    // and create temporary empty AST until the next async parse.
                    _editorTree.Invalidate();
                }
                else
                {
                    textChange.OldRange = context.OldRange;
                    textChange.NewRange = context.NewRange;

                    DeleteAndShiftElements(context);
                    Debug.Assert(_editorTree.AstRoot.Children.Count > 0);
                }

                _pendingChanges.Combine(textChange);
                _pendingChanges.Version = TextBuffer != null ? TextBuffer.CurrentSnapshot.Version.VersionNumber : 1;

                UpdateTreeTextSnapshot();
            } finally {
                // Lock must be released before firing events otherwise we may hang
                _editorTree.ReleaseWriteLock();
            }

            _editorTree.FireOnUpdateCompleted(TreeUpdateType.NodesRemoved);
        }
Example #2
0
        /// <summary>
        /// Handles non-trivial changes like changes that delete elements,
        /// change identifier names, introducing new braces: changes
        /// that cannot be handled without background parse.
        /// </summary>
        private void ProcessComplexChange(TextChangeContext context)
        {
            // Cancel background parse if it is running
            Cancel();
            var c = context.PendingChanges;

            try {
                // Get write lock since there may be concurrent readers
                // of the tree. Note that there are no concurrent writers
                // since changes can only come from a background parser
                // and are always applied from the main thread.
                _editorTree.AcquireWriteLock();
                int start, oldLength, newLength;

                if (Changes.FullParseRequired)
                {
                    // When full parse is required, change is like replace the entire file
                    start     = 0;
                    oldLength = c.OldTextProvider.Length;
                    newLength = c.NewTextProvider.Length;

                    // Remove damaged elements if any and reflect text change.
                    // the tree remains usable outside of the damaged scope.
                    _editorTree.InvalidateInRange(c.OldRange);
                    _editorTree.NotifyTextChange(c.Start, c.OldLength, c.NewLength);
                }
                else
                {
                    start     = c.Start;
                    oldLength = c.OldLength;
                    newLength = c.NewLength;

                    DeleteAndShiftElements(context);
                    Debug.Assert(_editorTree.AstRoot.Children.Count > 0);
                }

                var ttc = new TreeTextChange(start, oldLength, newLength, _editorTree.BufferSnapshot, EditorBuffer.CurrentSnapshot);
                Changes.Combine(ttc);
                Changes.Version = EditorBuffer?.CurrentSnapshot?.Version ?? 1;

                _editorTree.BufferSnapshot = EditorBuffer.CurrentSnapshot;
            } finally {
                // Lock must be released before firing events otherwise we may hang
                _editorTree.ReleaseWriteLock();
            }

            _editorTree.FireOnUpdateCompleted(TreeUpdateType.NodesRemoved);
        }
Example #3
0
        // internal for unit tests
        internal bool DeleteAndShiftElements(TextChangeContext context)
        {
            if (Thread.CurrentThread.ManagedThreadId != _ownerThreadId)
            {
                throw new ThreadStateException("Method should only be called on the main thread");
            }

            TextChange textChange      = context.PendingChanges;
            var        changeType      = textChange.TextChangeType;
            bool       elementsChanged = false;

            if (changeType == TextChangeType.Structure)
            {
                IAstNode changedElement = context.ChangedNode;
                int      start          = context.NewStart;

                // We delete change nodes unless node is a token node
                // which range can be modified such as string or comment
                var positionType = PositionType.Undefined;

                if (changedElement != null)
                {
                    IAstNode node;
                    positionType = changedElement.GetPositionNode(context.NewStart, out node);
                }

                bool deleteElements = (context.OldLength > 0) || (positionType != PositionType.Token);

                // In case of delete or replace we need to invalidate elements that were
                // damaged by the delete operation. We need to remove elements and their keys
                // so they won't be found by validator and incremental change analysis
                // will not be looking at zombies.

                if (deleteElements)
                {
                    _pendingChanges.FullParseRequired =
                        _editorTree.InvalidateInRange(_editorTree.AstRoot, context.OldRange, out elementsChanged);
                }
            }

            _editorTree.NotifyTextChange(context.NewStart, context.OldLength, context.NewLength);

            return(elementsChanged);
        }