예제 #1
0
        public override void UntrackDocument(ITextBuffer buffer)
        {
            if (buffer is null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            Debug.Assert(_joinableTaskContext.IsOnMainThread);

            var uri = _fileUriProvider.GetOrCreate(buffer);

            if (!_documents.TryGetValue(uri, out var lspDocument))
            {
                // We don't know about this document, noop.
                return;
            }

            // Given we're no longer tracking the document we don't want to pin the Uri to the current state of the buffer (could have been renamed to another Uri).
            _fileUriProvider.Remove(buffer);

            if (_documents.TryRemove(uri, out _))
            {
                var args = new LSPDocumentChangeEventArgs(lspDocument.CurrentSnapshot, @new: null, LSPDocumentChangeKind.Removed);
                Changed?.Invoke(this, args);
            }
            else
            {
                Debug.Fail($"Couldn't remove {uri.AbsolutePath}. This should never ever happen.");
            }

            lspDocument.Dispose();
        }
        public override void UpdateVirtualDocument <TVirtualDocument>(
            Uri hostDocumentUri,
            IReadOnlyList <ITextChange> changes,
            long hostDocumentVersion)
        {
            if (hostDocumentUri is null)
            {
                throw new ArgumentNullException(nameof(hostDocumentUri));
            }

            if (changes is null)
            {
                throw new ArgumentNullException(nameof(changes));
            }

            Debug.Assert(_joinableTaskContext.IsOnMainThread);

            if (!_documents.TryGetValue(hostDocumentUri, out var lspDocument))
            {
                // Don't know about document, noop.
                return;
            }

            var virtualDocumentAcquired = lspDocument.TryGetVirtualDocument <TVirtualDocument>(out var virtualDocument);

            if (changes.Count == 0 &&
                virtualDocumentAcquired &&
                virtualDocument.HostDocumentSyncVersion == hostDocumentVersion)
            {
                // The current virtual document already knows about this update. Ignore it so we don't prematurely invoke a change event.
                return;
            }

            var old        = lspDocument.CurrentSnapshot;
            var oldVirtual = virtualDocument.CurrentSnapshot;
            var @new       = lspDocument.UpdateVirtualDocument <TVirtualDocument>(changes, hostDocumentVersion);

            if (old == @new)
            {
                return;
            }

            if (!lspDocument.TryGetVirtualDocument <TVirtualDocument>(out var newVirtualDocument))
            {
                throw new InvalidOperationException("This should never ever happen.");
            }

            var newVirtual = newVirtualDocument.CurrentSnapshot;
            var args       = new LSPDocumentChangeEventArgs(
                old,
                @new,
                oldVirtual,
                newVirtual,
                LSPDocumentChangeKind.VirtualDocumentChanged);

            Changed?.Invoke(this, args);
        }
예제 #3
0
        // Internal for testing
        internal void DocumentManager_Changed(object sender, LSPDocumentChangeEventArgs args)
        {
            if (args is null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            lock (DocumentContextLock)
            {
                if (args.Kind == LSPDocumentChangeKind.Added)
                {
                    var lspDocument = args.New;
                    for (var i = 0; i < lspDocument.VirtualDocuments.Count; i++)
                    {
                        var virtualDocument = lspDocument.VirtualDocuments[i];

                        Debug.Assert(!_virtualDocumentContexts.ContainsKey(virtualDocument.Uri));

                        var virtualDocumentTextBuffer = virtualDocument.Snapshot.TextBuffer;
                        virtualDocumentTextBuffer.PostChanged        += VirtualDocumentBuffer_PostChanged;
                        _virtualDocumentContexts[virtualDocument.Uri] = new DocumentContext(_synchronizationTimeout);
                    }
                }
                else if (args.Kind == LSPDocumentChangeKind.Removed)
                {
                    var lspDocument = args.Old;
                    for (var i = 0; i < lspDocument.VirtualDocuments.Count; i++)
                    {
                        var virtualDocument = lspDocument.VirtualDocuments[i];

                        if (!_virtualDocumentContexts.TryGetValue(virtualDocument.Uri, out var virtualDocumentContext))
                        {
                            Debug.Fail("Could not locate virtual document context, it should have been added.");
                            continue;
                        }

                        var virtualDocumentTextBuffer = virtualDocument.Snapshot.TextBuffer;
                        virtualDocumentTextBuffer.PostChanged -= VirtualDocumentBuffer_PostChanged;

                        virtualDocumentContext.Dispose();
                        _virtualDocumentContexts.Remove(virtualDocument.Uri);
                    }
                }
                else if (args.Kind == LSPDocumentChangeKind.VirtualDocumentChanged)
                {
                    if (args.VirtualOld.Snapshot.Version == args.VirtualNew.Snapshot.Version)
                    {
                        // UpdateDocumentContextVersionInternal is typically invoked through a buffer notification,
                        //   however in the case where VirtualDocumentBase.Update is called with a zero change edit,
                        //   there won't be such an edit to hook into. Instead, we'll detect that case here and
                        //   update the document context version appropriately.
                        UpdateDocumentContextVersionInternal(args.VirtualNew.Snapshot.TextBuffer);
                    }
                }
            }
        }
예제 #4
0
        // Internal for testing
        internal void DocumentManager_Changed(object sender, LSPDocumentChangeEventArgs args)
        {
            if (args is null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            lock (DocumentContextLock)
            {
                if (args.Kind == LSPDocumentChangeKind.Added)
                {
                    var lspDocument = args.New;
                    for (var i = 0; i < lspDocument.VirtualDocuments.Count; i++)
                    {
                        var virtualDocument = lspDocument.VirtualDocuments[i];

                        Debug.Assert(!_virtualDocumentContexts.ContainsKey(virtualDocument.Uri));

                        var virtualDocumentTextBuffer = virtualDocument.Snapshot.TextBuffer;
                        virtualDocumentTextBuffer.PostChanged        += VirtualDocumentBuffer_PostChanged;
                        _virtualDocumentContexts[virtualDocument.Uri] = new DocumentContext(_synchronizationTimeout);
                    }
                }
                else if (args.Kind == LSPDocumentChangeKind.Removed)
                {
                    var lspDocument = args.Old;
                    for (var i = 0; i < lspDocument.VirtualDocuments.Count; i++)
                    {
                        var virtualDocument = lspDocument.VirtualDocuments[i];

                        Debug.Assert(_virtualDocumentContexts.ContainsKey(virtualDocument.Uri));

                        var virtualDocumentTextBuffer = virtualDocument.Snapshot.TextBuffer;
                        virtualDocumentTextBuffer.PostChanged -= VirtualDocumentBuffer_PostChanged;
                        _virtualDocumentContexts.Remove(virtualDocument.Uri);
                    }
                }
            }
        }
예제 #5
0
        public override void TrackDocument(ITextBuffer buffer)
        {
            if (buffer is null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            Debug.Assert(_joinableTaskContext.IsOnMainThread);

            var uri = _fileUriProvider.GetOrCreate(buffer);

            if (_documents.TryGetValue(uri, out _))
            {
                throw new InvalidOperationException($"Can not track document that's already being tracked {uri}");
            }

            var lspDocument = _documentFactory.Create(buffer);

            _documents[uri] = lspDocument;
            var args = new LSPDocumentChangeEventArgs(old: null, lspDocument.CurrentSnapshot, LSPDocumentChangeKind.Added);

            Changed?.Invoke(this, args);
        }
예제 #6
0
        private static void NotifyLSPDocumentAdded(LSPDocumentSnapshot lspDocument, DefaultLSPDocumentSynchronizer synchronizer)
        {
            var args = new LSPDocumentChangeEventArgs(old: null, @new: lspDocument, LSPDocumentChangeKind.Added);

            synchronizer.DocumentManager_Changed(sender: null, args);
        }