private ImmutableArray <char[]> GetChunks(SourceText text) { var largeText = text as LargeText; if (largeText != null) { var chunkField = text.GetType().GetField("_chunks", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); return((ImmutableArray <char[]>)chunkField.GetValue(text)); } else { return(ImmutableArray <char[]> .Empty); } }
protected override void ApplyDocumentTextChanged(DocumentId id, SourceText text) { var document = GetDocument(id); if (document == null) { return; } bool isOpen; var filePath = document.FilePath; var data = TextFileProvider.Instance.GetTextEditorData(filePath, out isOpen); // Guard against already done changes in linked files. // This shouldn't happen but the roslyn merging seems not to be working correctly in all cases :/ if (document.GetLinkedDocumentIds().Length > 0 && isOpen && !(text.GetType().FullName == "Microsoft.CodeAnalysis.Text.ChangedText")) { return; } SourceText formerText; if (changedFiles.TryGetValue(filePath, out formerText)) { if (formerText.Length == text.Length && formerText.ToString() == text.ToString()) { return; } } changedFiles [filePath] = text; Projection projection = null; foreach (var entry in ProjectionList) { var p = entry.Projections.FirstOrDefault(proj => FilePath.PathComparer.Equals(proj.Document.FileName, filePath)); if (p != null) { filePath = entry.File.FilePath; projection = p; break; } } SourceText oldFile; if (!isOpen || !document.TryGetText(out oldFile)) { oldFile = new MonoDevelopSourceText(data); } var changes = text.GetTextChanges(oldFile).OrderByDescending(c => c.Span.Start).ToList(); int delta = 0; if (!isOpen) { delta = ApplyChanges(projection, data, changes); var formatter = CodeFormatterService.GetFormatter(data.MimeType); var mp = GetMonoProject(CurrentSolution.GetProject(id.ProjectId)); string currentText = data.Text; foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } string str; if (change.NewText.Length == 0) { str = formatter.FormatText(mp.Policies, currentText, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { str = formatter.FormatText(mp.Policies, currentText, new TextSegment(startOffset, change.NewText.Length)); } data.ReplaceText(startOffset, change.NewText.Length, str); } data.Save(); OnDocumentTextChanged(id, new MonoDevelopSourceText(data), PreservationMode.PreserveValue); FileService.NotifyFileChanged(filePath); } else { var formatter = CodeFormatterService.GetFormatter(data.MimeType); var documentContext = IdeApp.Workbench.Documents.FirstOrDefault(d => FilePath.PathComparer.Compare(d.FileName, filePath) == 0); if (documentContext != null) { var editor = (TextEditor)data; using (var undo = editor.OpenUndoGroup()) { delta = ApplyChanges(projection, data, changes); foreach (var change in changes) { delta -= change.Span.Length - change.NewText.Length; var startOffset = change.Span.Start - delta; if (projection != null) { int originalOffset; if (projection.TryConvertFromProjectionToOriginal(startOffset, out originalOffset)) { startOffset = originalOffset; } } if (change.NewText.Length == 0) { formatter.OnTheFlyFormat(editor, documentContext, TextSegment.FromBounds(Math.Max(0, startOffset - 1), Math.Min(data.Length, startOffset + 1))); } else { formatter.OnTheFlyFormat(editor, documentContext, new TextSegment(startOffset, change.NewText.Length)); } } } } OnDocumentTextChanged(id, new MonoDevelopSourceText(data.CreateDocumentSnapshot()), PreservationMode.PreserveValue); Runtime.RunInMainThread(() => { if (IdeApp.Workbench != null) { foreach (var w in IdeApp.Workbench.Documents) { w.StartReparseThread(); } } }); } }