/// <summary> /// Get the preview temp file for a file extension. /// If the temp file already exists, use that one. Otherwise, create a new one. /// </summary> /// <param name="fileExtension">The file extension.</param> /// <returns>The preview temp file with file path, invisible editor and text buffer inforamtion.</returns> private PreviewTempFile GetPreviewTempFile(string fileExtension) { ArgumentValidation.CheckForNullReference(fileExtension, "fileExtension"); PreviewTempFile tempFile = null; // If the temp file already exists, use that one. if (!_tempFiles.TryGetValue(fileExtension, out tempFile)) { var failed = false; // Create a new preview temp file var tempFilePath = CreatePreviewTempFile(fileExtension); if (!File.Exists(tempFilePath)) { // Failed to create the temp file. failed = true; } else { // Open the file in invisible editor and get text buffer from it. IVsInvisibleEditor invisibleEditor = null; IVsTextLines textBuffer = null; if (RdtManager.Instance.TryGetTextLinesAndInvisibleEditor(tempFilePath, out invisibleEditor, out textBuffer) && invisibleEditor != null && textBuffer != null) { // Temp file is opened in invisible editor, and we got the text buffer from it. tempFile = new PreviewTempFile(tempFilePath, invisibleEditor, textBuffer); _tempFiles.Add(fileExtension, tempFile); } else { failed = true; } } if (failed) { // Failed to get InvisibleEditor or TextBuffer for that file, // throw exception. throw new InvalidOperationException( string.Format( CultureInfo.CurrentCulture, Resources.Exception_CannotGetTextBuffer, tempFilePath)); } } return(tempFile); }
/// <summary> /// Get the preview temp file for a file extension. /// If the temp file already exists, use that one. Otherwise, create a new one. /// </summary> /// <param name="fileExtension">The file extension.</param> /// <returns>The preview temp file with file path, invisible editor and text buffer inforamtion.</returns> private PreviewTempFile GetPreviewTempFile(string fileExtension) { ArgumentValidation.CheckForNullReference(fileExtension, "fileExtension"); PreviewTempFile tempFile = null; // If the temp file already exists, use that one. if (!_tempFiles.TryGetValue(fileExtension, out tempFile)) { var failed = false; // Create a new preview temp file var tempFilePath = CreatePreviewTempFile(fileExtension); if (!File.Exists(tempFilePath)) { // Failed to create the temp file. failed = true; } else { // Open the file in invisible editor and get text buffer from it. IVsInvisibleEditor invisibleEditor = null; IVsTextLines textBuffer = null; if (RdtManager.Instance.TryGetTextLinesAndInvisibleEditor(tempFilePath, out invisibleEditor, out textBuffer) && invisibleEditor != null && textBuffer != null) { // Temp file is opened in invisible editor, and we got the text buffer from it. tempFile = new PreviewTempFile(tempFilePath, invisibleEditor, textBuffer); _tempFiles.Add(fileExtension, tempFile); } else { failed = true; } } if (failed) { // Failed to get InvisibleEditor or TextBuffer for that file, // throw exception. throw new InvalidOperationException( string.Format( CultureInfo.CurrentCulture, Resources.Exception_CannotGetTextBuffer, tempFilePath)); } } return tempFile; }
/// <summary> /// Display the refactoring preview for a selected preview changes node. /// </summary> /// <param name="vsTextView">The text view to show the file contents.</param> /// <param name="fileChange">All changes in one file.</param> /// <param name="node">The selected PreviewChangesNode.</param> public void DisplayPreview(IVsTextView vsTextView, FileChange fileChange, PreviewChangesNode node) { ArgumentValidation.CheckForNullReference(vsTextView, "vsTextView"); ArgumentValidation.CheckForNullReference(node, "previewChangeNode"); if (fileChange != null) { // Get the temp file for this file extension, and copy all file content to the temp file text buffer PreviewTempFile tempFile = null; try { tempFile = GetPreviewTempFile(Path.GetExtension(fileChange.FileName)); } catch (InvalidOperationException) { // Failed to get text buffer, just set the text view to nothing. NativeMethods.ThrowOnFailure(vsTextView.SetBuffer(_bufferForNoChanges)); return; } // Copy the content of source file to that temp file text buffer CopyFileToBuffer(fileChange.FileName, tempFile.TextBuffer); // Create text markers on all changes on this file RefactoringOperationBase.ApplyChangesToOneFile(fileChange, tempFile.TextBuffer, true, node.ChangeProposal); // Set language service ID // Get Language service ID on this change node var languageServiceID = node.LanguageServiceID; if (languageServiceID == Guid.Empty && node.ChildList != null && node.ChildList.Count > 0) { // If can not get the language service ID, check if it has child nodes // if so, get the language service ID for first change in this file node. languageServiceID = node.ChildList[0].LanguageServiceID; } if (languageServiceID != Guid.Empty) { NativeMethods.ThrowOnFailure(tempFile.TextBuffer.SetLanguageServiceID(ref languageServiceID)); } // Set the vsTextView with textBuffer NativeMethods.ThrowOnFailure(vsTextView.SetBuffer(tempFile.TextBuffer)); // Ensure visible of first line and set the caret to position (0,0) ScrollInView(vsTextView, 0, 0, 0, 1); // If there is ChangeProposal, make sure that change is visible in the text view. // If ChangeProposal is null, that might be file node, make the first chagne visible. // Here we will only work with Text based change proposal. var visibleChange = node.ChangeProposal as TextChangeProposal; if (visibleChange == null) { // Try to get first change in this file if (node.ChildList != null && node.ChildList.Count > 0) { visibleChange = node.ChildList[0].ChangeProposal as TextChangeProposal; } } if (visibleChange != null) { // There are some changes, create TextSpan for first change, // and make the cursor position to that TextSpan. ScrollInView( vsTextView, visibleChange.StartLine, visibleChange.StartColumn, visibleChange.EndLine, visibleChange.EndColumn); } // Save the state, this will be used to refresh the text view when preview request // changed, such as check/uncheck _lastTextView = vsTextView; _lastDisplayedFileChange = fileChange; _lastDisplayedNode = node; } else { // No related file to this node, set nothing for the text view. NativeMethods.ThrowOnFailure(vsTextView.SetBuffer(_bufferForNoChanges)); } }