Example #1
0
        public ITextBuffer CreateTextBuffer(TextReader reader, IContentType contentType, long length, string traceId)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            if (contentType == null)
            {
                throw new ArgumentNullException("contentType");
            }
            if (length > int.MaxValue)
            {
                throw new InvalidOperationException(Strings.FileTooLarge);
            }

            ITextStorageLoader loader;

            if (length < TextModelOptions.CompressedStorageFileSizeThreshold)
            {
                loader = new SimpleTextStorageLoader(reader, (int)length);
            }
            else
            {
                loader = new CompressedTextStorageLoader(reader, (int)length, traceId);
            }
            StringRebuilder content = SimpleStringRebuilder.Create(loader);

            ITextBuffer buffer = Make(contentType, content, false);

            if (!loader.HasConsistentLineEndings)
            {
                // leave a sign that line endings are inconsistent. This is rather nasty but for now
                // we don't want to pollute the API with this factoid
                buffer.Properties.AddProperty("InconsistentLineEndings", true);
            }
            // leave a similar sign about the longest line in the buffer.
            buffer.Properties.AddProperty("LongestLineLength", loader.LongestLineLength);
            return(buffer);
        }
Example #2
0
        public ReloadResult Reload(EditOptions options)
        {
            if (_isDisposed)
            {
                throw new ObjectDisposedException("ITextDocument");
            }
            if (_raisingDirtyStateChangedEvent || _raisingFileActionChangedEvent)
            {
                throw new InvalidOperationException();
            }

            var              beforeSnapshot = _textBuffer.CurrentSnapshot;
            Encoding         newEncoding    = null;
            FallbackDetector fallbackDetector;

            try
            {
                _reloadingFile = true;

                // Load the file and read the contents to the text buffer

                long fileSize;
                using (var stream = TextDocumentFactoryService.OpenFileGuts(_filePath, out _lastModifiedTimeUtc, out fileSize))
                {
                    // We want to use the encoding indicated by a BoM if one is present because
                    // VS9's editor did so. We can't let the StreamReader below detect
                    // the byte order marks because we still want to be able to detect the
                    // fallback condition.
                    bool unused;
                    newEncoding = EncodedStreamReader.CheckForBoM(stream, isStreamEmpty: out unused);

                    Debug.Assert(newEncoding == null || newEncoding.GetPreamble().Length > 0);

                    // TODO: Consider using the encoder detector extensions as well.

                    if (newEncoding == null)
                    {
                        newEncoding = this.Encoding;
                    }

                    fallbackDetector = new FallbackDetector(newEncoding.DecoderFallback);
                    var modifiedEncoding = (Encoding)newEncoding.Clone();
                    modifiedEncoding.DecoderFallback = fallbackDetector;

                    using (var streamReader = new StreamReader(stream, modifiedEncoding, detectEncodingFromByteOrderMarks: false))
                    {
                        TextBuffer concreteBuffer = _textBuffer as TextBuffer;
                        if (concreteBuffer != null)
                        {
                            ITextStorageLoader loader;
                            if (fileSize < TextModelOptions.CompressedStorageFileSizeThreshold)
                            {
                                loader = new SimpleTextStorageLoader(streamReader, (int)fileSize);
                            }
                            else
                            {
                                loader = new CompressedTextStorageLoader(streamReader, (int)fileSize, _filePath);
                            }
                            StringRebuilder newContent = SimpleStringRebuilder.Create(loader);
                            if (!loader.HasConsistentLineEndings)
                            {
                                // leave a sign that line endings are inconsistent. This is rather nasty but for now
                                // we don't want to pollute the API with this factoid.
                                concreteBuffer.Properties["InconsistentLineEndings"] = true;
                            }
                            else
                            {
                                // this covers a really obscure case where on initial load the file had inconsistent line
                                // endings, but the UI settings were such that it was ignored, and since then the file has
                                // acquired consistent line endings and the UI settings have also changed.
                                concreteBuffer.Properties.RemoveProperty("InconsistentLineEndings");
                            }
                            // leave a similar sign about the longest line in the buffer.
                            concreteBuffer.Properties["LongestLineLength"] = loader.LongestLineLength;

                            concreteBuffer.ReloadContent(newContent, options, editTag: this);
                        }
                        else
                        {
                            // we may hit this path if somebody mocks the text buffer in a test.
                            using (var edit = _textBuffer.CreateEdit(options, null, editTag: this))
                            {
                                if (edit.Replace(new Span(0, edit.Snapshot.Length), streamReader.ReadToEnd()))
                                {
                                    edit.Apply();
                                }
                                else
                                {
                                    edit.Cancel();
                                }
                            }
                        }
                        Debug.Assert(streamReader.CurrentEncoding.CodePage == newEncoding.CodePage);
                        Debug.Assert(streamReader.CurrentEncoding.GetPreamble().Length == newEncoding.GetPreamble().Length);
                    }
                }
            }
            finally
            {
                _reloadingFile = false;
            }

            //The snapshot on a reload will change even if the contents of the before & after files are identical (differences will simply find an
            //empty set of changes) so this test is a measure of whether of not the reload succeeded.
            if (beforeSnapshot.Version.Next != null)
            {
                // Update status
                // set the "clean" reiterated version number to the reiterated version number of the version immediately
                // after the before snapshot (which is the state of the buffer after loading the document but before any
                // subsequent edits made in the text buffer changed events).
                _cleanReiteratedVersion = beforeSnapshot.Version.Next.ReiteratedVersionNumber;

                // TODO: the following event really should be queued up through the buffer group so that it comes before
                // the text changed event (and any subsequent text changed event invoked from an event handler)
                RaiseFileActionChangedEvent(_lastModifiedTimeUtc, FileActionTypes.ContentLoadedFromDisk, _filePath);
                this.Encoding = newEncoding;
                return(fallbackDetector.FallbackOccurred ? ReloadResult.SucceededWithCharacterSubstitutions : ReloadResult.Succeeded);
            }
            else
            {
                return(ReloadResult.Aborted);
            }
        }