private void ReloadBufferFromStream(Stream stream, long fileSize, EditOptions options, Encoding encoding) { using (var streamReader = new EncodedStreamReader.NonStreamClosingStreamReader(stream, encoding, detectEncodingFromByteOrderMarks: false)) { TextBuffer concreteBuffer = _textBuffer as TextBuffer; if (concreteBuffer != null) { StringRebuilder newContent = TextImageLoader.Load( streamReader, fileSize, out var newlineState, out var leadingWhitespaceState, out var longestLineLength); if (!newlineState.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"] = 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(); } } } } }
private void ReloadBufferFromStream(Stream stream, long fileSize, EditOptions options, Encoding encoding) { using (var streamReader = new EncodedStreamReader.NonStreamClosingStreamReader(stream, encoding, detectEncodingFromByteOrderMarks: false)) { TextBuffer concreteBuffer = _textBuffer as TextBuffer; if (concreteBuffer != null) { int longestLineLength; StringRebuilder newContent = TextImageLoader.Load(streamReader, fileSize, out var newlineState, out var leadingWhitespaceState, out longestLineLength); // Make the call to GetWhitespaceManager to add the manager to the properties. We don't need the return value here. _textDocumentFactoryService.WhitespaceManagerFactory.GetOrCreateWhitespaceManager(concreteBuffer, newlineState, leadingWhitespaceState); // Leave a sign about the longest line in the buffer. This is rather nasty, but for now // we don't want to pollute the API with this factoid concreteBuffer.Properties["LongestLineLength"] = 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(); } } } } }
public ITextDocument CreateAndLoadTextDocument(string filePath, IContentType contentType, bool attemptUtf8Detection, out bool characterSubstitutionsOccurred) { if (filePath == null) { throw new ArgumentNullException(nameof(filePath)); } if (contentType == null) { throw new ArgumentNullException(nameof(contentType)); } characterSubstitutionsOccurred = false; Encoding chosenEncoding = null; ITextBuffer buffer = null; DateTime lastModified; long fileSize; // select matching detectors without instantiating any var detectors = ExtensionSelector.SelectMatchingExtensions(OrderedEncodingDetectors, contentType); using (Stream stream = OpenFile(filePath, out lastModified, out fileSize)) { // First, look for a byte order marker and let the encoding detecters // suggest encodings. chosenEncoding = EncodedStreamReader.DetectEncoding(stream, detectors, GuardedOperations); // If that didn't produce a result, tentatively try to open as UTF 8. if (chosenEncoding == null && attemptUtf8Detection) { try { var detectorEncoding = new ExtendedCharacterDetector(); using (StreamReader reader = new EncodedStreamReader.NonStreamClosingStreamReader(stream, detectorEncoding, false)) { buffer = ((ITextBufferFactoryService2)BufferFactoryService).CreateTextBuffer(reader, contentType, fileSize, filePath); characterSubstitutionsOccurred = false; } if (detectorEncoding.DecodedExtendedCharacters) { // Valid UTF-8 but has bytes that are not merely ASCII. chosenEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); } else { // Valid UTF8 but no extended characters, so it's valid ASCII. // We don't use ASCII here because of the following scenario: // The user with a non-ENU system encoding opens a code file with ASCII-only contents chosenEncoding = DefaultEncoding; } } catch (DecoderFallbackException) { // Not valid UTF-8. // Proceed to the next if block to try the system's default codepage. Debug.Assert(buffer == null); buffer = null; stream.Position = 0; } } Debug.Assert(buffer == null || chosenEncoding != null); // If all else didn't work, use system's default encoding. if (chosenEncoding == null) { chosenEncoding = DefaultEncoding; } if (buffer == null) { var fallbackDetector = new FallbackDetector(chosenEncoding.DecoderFallback); var modifiedEncoding = (Encoding)chosenEncoding.Clone(); modifiedEncoding.DecoderFallback = fallbackDetector; Debug.Assert(stream.Position == 0); using (StreamReader reader = new EncodedStreamReader.NonStreamClosingStreamReader(stream, modifiedEncoding, detectEncodingFromByteOrderMarks: false)) { Debug.Assert(chosenEncoding.CodePage == reader.CurrentEncoding.CodePage); buffer = ((ITextBufferFactoryService2)BufferFactoryService).CreateTextBuffer(reader, contentType, fileSize, filePath); } characterSubstitutionsOccurred = fallbackDetector.FallbackOccurred; } } TextDocument textDocument = new TextDocument(buffer, filePath, lastModified, this, chosenEncoding, attemptUtf8Detection: attemptUtf8Detection); RaiseTextDocumentCreated(textDocument); return(textDocument); }