public void UpdateText(SourceText newText)
        {
            _updatding = true;
            _editor.Document.BeginUpdate();
            try
            {
                var changes = newText.GetTextChanges(_currentText);

                var offset = 0;

                foreach (var change in changes)
                {
                    _editor.Document.Replace(change.Span.Start + offset, change.Span.Length, new StringTextSource(change.NewText));

                    offset += change.NewText.Length - change.Span.Length;
                }

                _currentText = newText;
            }
            finally
            {
                _updatding = false;
                _editor.Document.EndUpdate();
            }
        }
Esempio n. 2
0
        protected override void ApplyDocumentTextChanged(DocumentId document, SourceText newText)
        {
            if (_openDocumentId != document)
            {
                return;
            }

            ITextSnapshot appliedText;
            using (var edit = _openTextContainer.GetTextBuffer().CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null))
            {
                var oldText = _openTextContainer.CurrentText;
                var changes = newText.GetTextChanges(oldText);

                foreach (var change in changes)
                {
                    edit.Replace(change.Span.Start, change.Span.Length, change.NewText);
                }

                appliedText = edit.Apply();
            }

            this.OnDocumentTextChanged(document, appliedText.AsText(), PreservationMode.PreserveIdentity);
        }
Esempio n. 3
0
		protected override async void ApplyDocumentTextChanged (DocumentId id, SourceText text)
		{
			var document = GetDocument (id);
			if (document == null)
				return;
			bool isOpen;
			var filePath = document.FilePath;

			Projection projection = null;
			foreach (var entry in ProjectionList) {
				var p = entry.Projections.FirstOrDefault (proj => proj?.Document?.FileName != null && FilePath.PathComparer.Equals (proj.Document.FileName, filePath));
				if (p != null) {
					filePath = entry.File.FilePath;
					projection = p;
					break;
				}
			}

			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;
			lock (changedFiles) {
				if (changedFiles.TryGetValue (filePath, out formerText)) {
					if (formerText.Length == text.Length && formerText.ToString () == text.ToString ())
						return;
				}
				changedFiles [filePath] = text;
			}

			SourceText oldFile;
			if (!isOpen || !document.TryGetText (out oldFile)) {
				oldFile = await document.GetTextAsync ();
			}
			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);
				if (formatter.SupportsPartialDocumentFormatting) {
					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 ();
				if (projection != null) {
					await UpdateProjectionsDocuments (document, data);
				} else {
					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);
				var root = await projectChanges.NewProject.GetDocument (id).GetSyntaxRootAsync ();
				var annotatedNode = root.DescendantNodesAndSelf ().FirstOrDefault (n => n.HasAnnotation (TypeSystemService.InsertionModeAnnotation));
				SyntaxToken? renameTokenOpt = root.GetAnnotatedNodesAndTokens (Microsoft.CodeAnalysis.CodeActions.RenameAnnotation.Kind)
												  .Where (s => s.IsToken)
												  .Select (s => s.AsToken ())
												  .Cast<SyntaxToken?> ()
												  .FirstOrDefault ();

				if (documentContext != null) {
					var editor = (TextEditor)data;
					await Runtime.RunInMainThread (async () => {
						using (var undo = editor.OpenUndoGroup ()) {
							var oldVersion = editor.Version;
							delta = ApplyChanges (projection, data, changes);
							var versionBeforeFormat = editor.Version;

							if (formatter.SupportsOnTheFlyFormatting) {
								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));
									}
								}
							}
							if (annotatedNode != null && GetInsertionPoints != null) {
								IdeApp.Workbench.Documents.First (d => d.FileName == editor.FileName).Select ();
								var formattedVersion = editor.Version;

								int startOffset = versionBeforeFormat.MoveOffsetTo (editor.Version, annotatedNode.Span.Start);
								int endOffset = versionBeforeFormat.MoveOffsetTo (editor.Version, annotatedNode.Span.End);

								// alway whole line start & delimiter
								var startLine = editor.GetLineByOffset (startOffset);
								startOffset = startLine.Offset;

								var endLine = editor.GetLineByOffset (endOffset);
								endOffset = endLine.EndOffsetIncludingDelimiter + 1;

								var insertionCursorSegment = TextSegment.FromBounds (startOffset, endOffset);
								string textToInsert = editor.GetTextAt (insertionCursorSegment).TrimEnd ();
								editor.RemoveText (insertionCursorSegment);
								var insertionPoints = await GetInsertionPoints (editor, editor.CaretOffset);
								if (insertionPoints.Count == 0) {
									// Just to get sure if no insertion points -> go back to the formatted version.
									var textChanges = editor.Version.GetChangesTo (formattedVersion).ToList ();
									using (var undo2 = editor.OpenUndoGroup ()) {
										foreach (var v in textChanges) {
											editor.ReplaceText (v.Offset, v.RemovalLength, v.InsertedText);
										}
									}
									return;
								}
								string insertionModeOperation;
								const int CSharpMethodKind = 8875;


								bool isMethod = annotatedNode.RawKind == CSharpMethodKind;

								if (!isMethod) {
									// atm only for generate field/property : remove all new lines generated & just insert the plain node.
									// for methods it's not so easy because of "extract code" changes.
									foreach (var v in editor.Version.GetChangesTo (oldVersion).ToList ()) {
										editor.ReplaceText (v.Offset, v.RemovalLength, v.InsertedText);
									}
								}

								switch (annotatedNode.RawKind) {
								case 8873: // C# field
									insertionModeOperation = GettextCatalog.GetString ("Insert Field");
									break;
								case CSharpMethodKind:
									insertionModeOperation = GettextCatalog.GetString ("Insert Method");
									break;
								case 8892: // C# property 
									insertionModeOperation = GettextCatalog.GetString ("Insert Property");
									break;
								default:
									insertionModeOperation = GettextCatalog.GetString ("Insert Code");
									break;
								}

								var options = new InsertionModeOptions (
									insertionModeOperation,
									insertionPoints,
									point => {
										if (!point.Success)
											return;
										point.InsertionPoint.Insert (editor, textToInsert);
									}
								);
								options.ModeExitedAction += delegate (InsertionCursorEventArgs args) {
									if (!args.Success) {
										var textChanges = editor.Version.GetChangesTo (oldVersion).ToList ();
										using (var undo2 = editor.OpenUndoGroup ()) {
											foreach (var v in textChanges) {
												editor.ReplaceText (v.Offset, v.RemovalLength, v.InsertedText);
											}
										}
									}
								};
								for (int i = 0; i < insertionPoints.Count; i++) {
									if (insertionPoints [i].Location.Line < editor.CaretLine) {
										options.FirstSelectedInsertionPoint = Math.Min (isMethod ? i + 1 : i, insertionPoints.Count - 1);
									} else {
										break;
									}
								}
								options.ModeExitedAction += delegate {
									if (renameTokenOpt.HasValue)
										StartRenameSession (editor, documentContext, versionBeforeFormat, renameTokenOpt.Value);
								};
								editor.StartInsertionMode (options);
							}
						}
					});
				}

				if (projection != null) {
					await UpdateProjectionsDocuments (document, data);
				} else {
					OnDocumentTextChanged (id, new MonoDevelopSourceText (data.CreateDocumentSnapshot ()), PreservationMode.PreserveValue);
				}
				await Runtime.RunInMainThread (() => {
						if (IdeApp.Workbench != null)
						foreach (var w in IdeApp.Workbench.Documents)
							w.StartReparseThread ();
				});
			}
		}
            private static void UpdateText(SourceText newText, ITextBuffer buffer, EditOptions options)
            {
                using (var edit = buffer.CreateEdit(options, reiteratedVersionNumber: null, editTag: null))
                {
                    var oldSnapshot = buffer.CurrentSnapshot;
                    var oldText = oldSnapshot.AsText();
                    var changes = newText.GetTextChanges(oldText);

                    Workspace workspace = null;
                    if (Workspace.TryGetWorkspace(oldText.Container, out workspace))
                    {
                        var undoService = workspace.Services.GetService<ISourceTextUndoService>();
                        undoService.BeginUndoTransaction(oldSnapshot);
                    }

                    foreach (var change in changes)
                    {
                        edit.Replace(change.Span.Start, change.Span.Length, change.NewText);
                    }

                    edit.Apply();
                }
            }
 // Stolen from Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.DocumentProvider.StandardTextDocument
 private static void UpdateText(SourceText newText, ITextBuffer buffer, EditOptions options)
 {
     using (ITextEdit textEdit = buffer.CreateEdit(options, null, null))
     {
         SourceText oldText = buffer.CurrentSnapshot.AsText();
         foreach (var current in newText.GetTextChanges(oldText))
         {
             textEdit.Replace(current.Span.Start, current.Span.Length, current.NewText);
         }
         textEdit.Apply();
     }
 }
Esempio n. 6
0
        internal void Update(SourceText newText)
        {
            var buffer = GetTextBuffer();
            using (var edit = buffer.CreateEdit(EditOptions.DefaultMinimalChange, reiteratedVersionNumber: null, editTag: null))
            {
                var oldText = buffer.CurrentSnapshot.AsText();
                var changes = newText.GetTextChanges(oldText);

                foreach (var change in changes)
                {
                    edit.Replace(change.Span.Start, change.Span.Length, change.NewText);
                }

                edit.Apply();
            }
        }
		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 ();
				});
			}
		}
            private static void UpdateText(SourceText newText, ITextBuffer buffer, EditOptions options)
            {
                using (var edit = buffer.CreateEdit(options, reiteratedVersionNumber: null, editTag: null))
                {
                    var oldText = buffer.CurrentSnapshot.AsText();
                    var changes = newText.GetTextChanges(oldText);

                    foreach (var change in changes)
                    {
                        edit.Replace(change.Span.Start, change.Span.Length, change.NewText);
                    }

                    edit.Apply();
                }
            }
Esempio n. 9
0
        public void UpdateText(SourceText newText)
        {
            var subjectBuffer = (IProjectionBuffer)this.GetOpenTextBuffer();
            var originalSnapshot = subjectBuffer.CurrentSnapshot;
            var originalText = originalSnapshot.AsText();

            var changes = newText.GetTextChanges(originalText);

            IEnumerable<int> affectedVisibleSpanIndices = null;
            var editorVisibleSpansInOriginal = SharedPools.Default<List<TextSpan>>().AllocateAndClear();

            try
            {
                var originalDocument = _workspace.CurrentSolution.GetDocument(this.Id);

                editorVisibleSpansInOriginal.AddRange(GetEditorVisibleSpans());
                var newChanges = FilterTextChanges(originalText, editorVisibleSpansInOriginal, changes).ToList();
                if (newChanges.Count == 0)
                {
                    // no change to apply
                    return;
                }

                ApplyChanges(subjectBuffer, newChanges, editorVisibleSpansInOriginal, out affectedVisibleSpanIndices);
                AdjustIndentation(subjectBuffer, affectedVisibleSpanIndices);
            }
            finally
            {
                SharedPools.Default<HashSet<int>>().ClearAndFree((HashSet<int>)affectedVisibleSpanIndices);
                SharedPools.Default<List<TextSpan>>().ClearAndFree(editorVisibleSpansInOriginal);
            }
        }