Exemple #1
0
        /// <summary>
        ///     Get FileChange for a previewNode.
        ///     After user clicks a preview node, the preview dialog will show
        ///     content of the file this change will be applied to.  And the content
        ///     of that file will contains all the selected changes to that file and
        ///     will show user the version with changes already applied.
        /// </summary>
        /// <param name="previewNode"></param>
        /// <returns>
        ///     FileChange related to this node.  If this change is atomic change,
        ///     or the node is file node, it will return the FileChange object for
        ///     the file it is changing.
        ///     If the node is a group node, it will return null.
        /// </returns>
        public FileChange GetFileChange(PreviewChangesNode previewNode)
        {
            ArgumentValidation.CheckForNullReference(previewNode, "previewNode");

            string fileName       = null;
            var    changeProposal = previewNode.ChangeProposal;

            if (changeProposal != null)
            {
                // Preview Node for atomic change
                fileName = changeProposal.FileName;
            }
            else
            {
                // Look at direct child, if that child is an atomic change,
                // then get filename for it, otherwise, just leave the filename as null
                if (previewNode.ChildList != null &&
                    previewNode.ChildList.Count > 0)
                {
                    var proposal = previewNode.ChildList[0].ChangeProposal;
                    if (proposal != null)
                    {
                        fileName = proposal.FileName;
                    }
                }
            }

            FileChange fileChange = null;

            if (fileName != null)
            {
                _fileChanges.TryGetValue(fileName, out fileChange);
            }
            return(fileChange);
        }
        /// <summary>
        ///     Add child node to this node.
        /// </summary>
        /// <param name="node"></param>
        public void AddChildNode(PreviewChangesNode node)
        {
            if (_childList == null)
            {
                _childList = new List <PreviewChangesNode>();
            }
            node._parent = this;
            _childList.Add(node);

            ComputeCheckedState();
        }
 protected static void AddCheckBoxToPreviewNode(PreviewChangesNode previewNode, bool setCheckState, bool check)
 {
     ArgumentValidation.CheckForNullReference(previewNode, "previewNode");
     previewNode.ShowCheckBox = true;
     if (setCheckState)
     {
         if (check)
         {
             previewNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked;
         }
         else
         {
             previewNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;
         }
     }
 }
        protected static PreviewChangesNode CreatePreviewNode(
            string displayText,
            ushort icon,
            IntPtr imageList,
            TextChangeProposal proposal,
            bool forceSelection,
            bool enableChangeUncheck,
            bool isChecked)
        {
            var displayData = new VSTREEDISPLAYDATA();

            if (forceSelection)
            {
                Debug.Assert(!string.IsNullOrEmpty(displayText), "display text is null or empty");
                Debug.Assert(proposal != null, "proposal is null");

                var length = displayText.Length;
                displayText = displayText.TrimStart();
                var spaceLength = length - displayText.Length;

                displayData.State             = (uint)_VSTREEDISPLAYSTATE.TDS_FORCESELECT;
                displayData.ForceSelectStart  = (ushort)(proposal.StartColumn - spaceLength);
                displayData.ForceSelectLength = (ushort)(proposal.EndColumn - proposal.StartColumn);
            }

            if (imageList != IntPtr.Zero)
            {
                displayData.hImageList = imageList;
            }

            displayData.Image = displayData.SelectedImage = icon;

            var node = new PreviewChangesNode(displayText, displayData, displayText, null, proposal);

            if (enableChangeUncheck)
            {
                AddCheckBoxToPreviewNode(node, true, isChecked);
            }

            return(node);
        }
        protected static List <PreviewChangesNode> CreatePreviewNodesForVsLang(
            IList <FileChange> fileChanges, bool placeNodesUnderSingleRoot = false)
        {
            var vsLangObjectNodes      = new List <PreviewChangesNode>();
            var rootToFileToChangesMap = new Dictionary <string, Dictionary <string, List <PreviewChangesNode> > >();
            var isCSharpChange         = true;

            foreach (var fileChange in fileChanges)
            {
                if (fileChange.ChangeList != null)
                {
                    if (fileChange.ChangeList.Count > 0)
                    {
                        using (var textBuffer = VsTextLinesFromFile.Load(fileChange.FileName))
                        {
                            if (textBuffer != null)
                            {
                                foreach (
                                    var vsLangTextChange in
                                    fileChange.ChangeList.SelectMany(cl => cl.Value).OfType <VsLangTextChangeProposal>())
                                {
                                    if (vsLangTextChange.IsRootChange)
                                    {
                                        // Create object definition node
                                        var rootNode = new PreviewChangesNode(
                                            vsLangTextChange.ObjectDefinitionFullName
                                            , new VSTREEDISPLAYDATA()
                                            , vsLangTextChange.ObjectDefinitionFullName
                                            , new List <PreviewChangesNode>()
                                            , vsLangTextChange);

                                        rootNode.CheckState = vsLangTextChange.Included
                                                                  ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked
                                                                  : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;
                                        vsLangObjectNodes.Add(rootNode);

                                        // It's possible that a non-root change was processed first, in which case the dictionary will already be updated
                                        // with the root node name. This means we need to check the dictionary before adding to it.
                                        if (!rootToFileToChangesMap.ContainsKey(vsLangTextChange.ObjectDefinitionFullName))
                                        {
                                            rootToFileToChangesMap.Add(
                                                vsLangTextChange.ObjectDefinitionFullName,
                                                new Dictionary <string, List <PreviewChangesNode> >());
                                        }
                                    }
                                    else
                                    {
                                        // Get display text, trim the leading space of the text for display purpose.
                                        var displayText = string.Empty;
                                        int lineLength;

                                        if (ErrorHandler.Succeeded(textBuffer.GetLengthOfLine(vsLangTextChange.StartLine, out lineLength)))
                                        {
                                            if (
                                                ErrorHandler.Succeeded(
                                                    textBuffer.GetLineText(
                                                        vsLangTextChange.StartLine, 0, vsLangTextChange.StartLine, lineLength,
                                                        out displayText)))
                                            {
                                                var length = displayText.Length;
                                                displayText = displayText.TrimStart();
                                                var spaceLength = length - displayText.Length;

                                                Debug.Assert(
                                                    spaceLength <= vsLangTextChange.StartColumn,
                                                    "Start column of selection is negative, HydratedVsLangRefactor.CreatePreviewNodeForChanges()");

                                                if (spaceLength <= vsLangTextChange.StartColumn)
                                                {
                                                    var changeNodeDisplayData = new VSTREEDISPLAYDATA();
                                                    changeNodeDisplayData.State            = (uint)_VSTREEDISPLAYSTATE.TDS_FORCESELECT;
                                                    changeNodeDisplayData.ForceSelectStart =
                                                        (ushort)(vsLangTextChange.StartColumn - spaceLength);
                                                    changeNodeDisplayData.ForceSelectLength = (ushort)(vsLangTextChange.Length);

                                                    var changeNode = new PreviewChangesNode(
                                                        displayText, changeNodeDisplayData, displayText, null, vsLangTextChange);

                                                    // Add checked checkbox
                                                    changeNode.ShowCheckBox = true;
                                                    changeNode.CheckState   = vsLangTextChange.Included
                                                                                ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked
                                                                                : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;

                                                    // Apply the language service to this change.
                                                    Guid languageServiceId;
                                                    textBuffer.GetLanguageServiceID(out languageServiceId);
                                                    changeNode.LanguageServiceID = languageServiceId;

                                                    Dictionary <string, List <PreviewChangesNode> > fileToChangesMap;
                                                    if (rootToFileToChangesMap.TryGetValue(
                                                            vsLangTextChange.ObjectDefinitionFullName, out fileToChangesMap))
                                                    {
                                                        List <PreviewChangesNode> changeNodes;
                                                        if (fileToChangesMap.TryGetValue(fileChange.FileName, out changeNodes))
                                                        {
                                                            changeNodes.Add(changeNode);
                                                        }
                                                        else
                                                        {
                                                            // There are no changes for the file listed under this root node, so we need to create it
                                                            changeNodes = new List <PreviewChangesNode> {
                                                                changeNode
                                                            };
                                                            fileToChangesMap.Add(fileChange.FileName, changeNodes);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        // There are no changes processed yet for this object name, so we need to update our dictionary with
                                                        // markers for creating a new root node, a new file node, and a new change node.
                                                        fileToChangesMap = new Dictionary <string, List <PreviewChangesNode> >();
                                                        fileToChangesMap.Add(
                                                            fileChange.FileName, new List <PreviewChangesNode> {
                                                            changeNode
                                                        });
                                                        rootToFileToChangesMap.Add(
                                                            vsLangTextChange.ObjectDefinitionFullName, fileToChangesMap);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Now that all the changes have been sorted under the correct root nodes in our dictionary, create the File nodes that connect
            // the root nodes to the change nodes.
            foreach (var rootNode in vsLangObjectNodes)
            {
                Dictionary <string, List <PreviewChangesNode> > fileToChangesMap;
                if (rootToFileToChangesMap.TryGetValue(rootNode.DisplayText, out fileToChangesMap))
                {
                    if (fileToChangesMap != null)
                    {
                        foreach (var fileName in fileToChangesMap.Keys)
                        {
                            var fileNodeDisplayData = new VSTREEDISPLAYDATA();

                            if (FileExtensions.VbExt.Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase))
                            {
                                fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT;
                                isCSharpChange            = false;
                            }
                            else
                            {
                                fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE;
                            }

                            var shortFileName = Path.GetFileName(fileName);
                            var checkState    = DetermineCheckState(fileToChangesMap[fileName]);
                            var fileNode      = new PreviewChangesNode(shortFileName, fileNodeDisplayData, shortFileName, null, null);
                            fileNode.AddChildNodes(fileToChangesMap[fileName]);

                            // Add checked checkbox
                            fileNode.ShowCheckBox = true;
                            fileNode.CheckState   = checkState;
                            rootNode.AddChildNode(fileNode);

                            // Update root check state
                            if (rootNode.ChildList.Count == 1)
                            {
                                // This is the first child, so the root should match the child check state
                                rootNode.CheckState = checkState;
                            }
                            else
                            {
                                switch (rootNode.CheckState)
                                {
                                case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked:
                                {
                                    if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked ||
                                        checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked)
                                    {
                                        rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked;
                                    }
                                    break;
                                }

                                case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked:
                                {
                                    if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked ||
                                        checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked)
                                    {
                                        rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked;
                                    }
                                    break;
                                }
                                }
                            }
                        }
                    }
                }
            }

            if (placeNodesUnderSingleRoot)
            {
                PreviewChangesNode rootNode;
                var fileNodeDisplayData = new VSTREEDISPLAYDATA();

                if (isCSharpChange)
                {
                    fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE;
                    rootNode = new PreviewChangesNode(CSharpRootNodeText, fileNodeDisplayData, null, null, null);
                }
                else
                {
                    fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT;
                    rootNode = new PreviewChangesNode(VBRootNodeText, fileNodeDisplayData, null, null, null);
                }

                rootNode.ShowCheckBox = true;
                rootNode.CheckState   = DetermineCheckState(vsLangObjectNodes);
                rootNode.AddChildNodes(vsLangObjectNodes);
                return(new List <PreviewChangesNode> {
                    rootNode
                });
            }
            else
            {
                return(vsLangObjectNodes);
            }
        }
Exemple #6
0
        /// <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));
            }
        }
        /// <summary>
        ///     Get FileChange for a previewNode.
        ///     After user clicks a preview node, the preview dialog will show
        ///     content of the file this change will be applied to.  And the content
        ///     of that file will contains all the selected changes to that file and
        ///     will show user the version with changes already applied.
        /// </summary>
        /// <param name="previewNode"></param>
        /// <returns>
        ///     FileChange related to this node.  If this change is atomic change,
        ///     or the node is file node, it will return the FileChange object for
        ///     the file it is changing.
        ///     If the node is a group node, it will return null.
        /// </returns>
        public FileChange GetFileChange(PreviewChangesNode previewNode)
        {
            ArgumentValidation.CheckForNullReference(previewNode, "previewNode");

            string fileName = null;
            var changeProposal = previewNode.ChangeProposal;
            if (changeProposal != null)
            {
                // Preview Node for atomic change
                fileName = changeProposal.FileName;
            }
            else
            {
                // Look at direct child, if that child is an atomic change,
                // then get filename for it, otherwise, just leave the filename as null
                if (previewNode.ChildList != null
                    && previewNode.ChildList.Count > 0)
                {
                    var proposal = previewNode.ChildList[0].ChangeProposal;
                    if (proposal != null)
                    {
                        fileName = proposal.FileName;
                    }
                }
            }

            FileChange fileChange = null;

            if (fileName != null)
            {
                _fileChanges.TryGetValue(fileName, out fileChange);
            }
            return fileChange;
        }
        protected static List<PreviewChangesNode> CreatePreviewNodesForVsLang(
            IList<FileChange> fileChanges, bool placeNodesUnderSingleRoot = false)
        {
            var vsLangObjectNodes = new List<PreviewChangesNode>();
            var rootToFileToChangesMap = new Dictionary<string, Dictionary<string, List<PreviewChangesNode>>>();
            var isCSharpChange = true;

            foreach (var fileChange in fileChanges)
            {
                if (fileChange.ChangeList != null)
                {
                    if (fileChange.ChangeList.Count > 0)
                    {
                        using (var textBuffer = VsTextLinesFromFile.Load(fileChange.FileName))
                        {
                            if (textBuffer != null)
                            {
                                foreach (
                                    var vsLangTextChange in
                                        fileChange.ChangeList.SelectMany(cl => cl.Value).OfType<VsLangTextChangeProposal>())
                                {
                                    if (vsLangTextChange.IsRootChange)
                                    {
                                        // Create object definition node                                        
                                        var rootNode = new PreviewChangesNode(
                                            vsLangTextChange.ObjectDefinitionFullName
                                            , new VSTREEDISPLAYDATA()
                                            , vsLangTextChange.ObjectDefinitionFullName
                                            , new List<PreviewChangesNode>()
                                            , vsLangTextChange);

                                        rootNode.CheckState = vsLangTextChange.Included
                                                                  ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked
                                                                  : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;
                                        vsLangObjectNodes.Add(rootNode);

                                        // It's possible that a non-root change was processed first, in which case the dictionary will already be updated
                                        // with the root node name. This means we need to check the dictionary before adding to it.
                                        if (!rootToFileToChangesMap.ContainsKey(vsLangTextChange.ObjectDefinitionFullName))
                                        {
                                            rootToFileToChangesMap.Add(
                                                vsLangTextChange.ObjectDefinitionFullName,
                                                new Dictionary<string, List<PreviewChangesNode>>());
                                        }
                                    }
                                    else
                                    {
                                        // Get display text, trim the leading space of the text for display purpose.
                                        var displayText = string.Empty;
                                        int lineLength;

                                        if (ErrorHandler.Succeeded(textBuffer.GetLengthOfLine(vsLangTextChange.StartLine, out lineLength)))
                                        {
                                            if (
                                                ErrorHandler.Succeeded(
                                                    textBuffer.GetLineText(
                                                        vsLangTextChange.StartLine, 0, vsLangTextChange.StartLine, lineLength,
                                                        out displayText)))
                                            {
                                                var length = displayText.Length;
                                                displayText = displayText.TrimStart();
                                                var spaceLength = length - displayText.Length;

                                                Debug.Assert(
                                                    spaceLength <= vsLangTextChange.StartColumn,
                                                    "Start column of selection is negative, HydratedVsLangRefactor.CreatePreviewNodeForChanges()");

                                                if (spaceLength <= vsLangTextChange.StartColumn)
                                                {
                                                    var changeNodeDisplayData = new VSTREEDISPLAYDATA();
                                                    changeNodeDisplayData.State = (uint)_VSTREEDISPLAYSTATE.TDS_FORCESELECT;
                                                    changeNodeDisplayData.ForceSelectStart =
                                                        (ushort)(vsLangTextChange.StartColumn - spaceLength);
                                                    changeNodeDisplayData.ForceSelectLength = (ushort)(vsLangTextChange.Length);

                                                    var changeNode = new PreviewChangesNode(
                                                        displayText, changeNodeDisplayData, displayText, null, vsLangTextChange);

                                                    // Add checked checkbox
                                                    changeNode.ShowCheckBox = true;
                                                    changeNode.CheckState = vsLangTextChange.Included
                                                                                ? __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked
                                                                                : __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;

                                                    // Apply the language service to this change.
                                                    Guid languageServiceId;
                                                    textBuffer.GetLanguageServiceID(out languageServiceId);
                                                    changeNode.LanguageServiceID = languageServiceId;

                                                    Dictionary<string, List<PreviewChangesNode>> fileToChangesMap;
                                                    if (rootToFileToChangesMap.TryGetValue(
                                                        vsLangTextChange.ObjectDefinitionFullName, out fileToChangesMap))
                                                    {
                                                        List<PreviewChangesNode> changeNodes;
                                                        if (fileToChangesMap.TryGetValue(fileChange.FileName, out changeNodes))
                                                        {
                                                            changeNodes.Add(changeNode);
                                                        }
                                                        else
                                                        {
                                                            // There are no changes for the file listed under this root node, so we need to create it
                                                            changeNodes = new List<PreviewChangesNode> { changeNode };
                                                            fileToChangesMap.Add(fileChange.FileName, changeNodes);
                                                        }
                                                    }
                                                    else
                                                    {
                                                        // There are no changes processed yet for this object name, so we need to update our dictionary with
                                                        // markers for creating a new root node, a new file node, and a new change node.
                                                        fileToChangesMap = new Dictionary<string, List<PreviewChangesNode>>();
                                                        fileToChangesMap.Add(
                                                            fileChange.FileName, new List<PreviewChangesNode> { changeNode });
                                                        rootToFileToChangesMap.Add(
                                                            vsLangTextChange.ObjectDefinitionFullName, fileToChangesMap);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Now that all the changes have been sorted under the correct root nodes in our dictionary, create the File nodes that connect
            // the root nodes to the change nodes.
            foreach (var rootNode in vsLangObjectNodes)
            {
                Dictionary<string, List<PreviewChangesNode>> fileToChangesMap;
                if (rootToFileToChangesMap.TryGetValue(rootNode.DisplayText, out fileToChangesMap))
                {
                    if (fileToChangesMap != null)
                    {
                        foreach (var fileName in fileToChangesMap.Keys)
                        {
                            var fileNodeDisplayData = new VSTREEDISPLAYDATA();

                            if (FileExtensions.VbExt.Equals(Path.GetExtension(fileName), StringComparison.OrdinalIgnoreCase))
                            {
                                fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT;
                                isCSharpChange = false;
                            }
                            else
                            {
                                fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE;
                            }

                            var shortFileName = Path.GetFileName(fileName);
                            var checkState = DetermineCheckState(fileToChangesMap[fileName]);
                            var fileNode = new PreviewChangesNode(shortFileName, fileNodeDisplayData, shortFileName, null, null);
                            fileNode.AddChildNodes(fileToChangesMap[fileName]);

                            // Add checked checkbox
                            fileNode.ShowCheckBox = true;
                            fileNode.CheckState = checkState;
                            rootNode.AddChildNode(fileNode);

                            // Update root check state
                            if (rootNode.ChildList.Count == 1)
                            {
                                // This is the first child, so the root should match the child check state
                                rootNode.CheckState = checkState;
                            }
                            else
                            {
                                switch (rootNode.CheckState)
                                {
                                    case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked:
                                        {
                                            if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked
                                                || checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked)
                                            {
                                                rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked;
                                            }
                                            break;
                                        }
                                    case __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked:
                                        {
                                            if (checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked
                                                || checkState == __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked)
                                            {
                                                rootNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_PartiallyChecked;
                                            }
                                            break;
                                        }
                                }
                            }
                        }
                    }
                }
            }

            if (placeNodesUnderSingleRoot)
            {
                PreviewChangesNode rootNode;
                var fileNodeDisplayData = new VSTREEDISPLAYDATA();

                if (isCSharpChange)
                {
                    fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_CSHARPFILE;
                    rootNode = new PreviewChangesNode(CSharpRootNodeText, fileNodeDisplayData, null, null, null);
                }
                else
                {
                    fileNodeDisplayData.Image = fileNodeDisplayData.SelectedImage = CommonConstants.OM_GLYPH_VBPROJECT;
                    rootNode = new PreviewChangesNode(VBRootNodeText, fileNodeDisplayData, null, null, null);
                }

                rootNode.ShowCheckBox = true;
                rootNode.CheckState = DetermineCheckState(vsLangObjectNodes);
                rootNode.AddChildNodes(vsLangObjectNodes);
                return new List<PreviewChangesNode> { rootNode };
            }
            else
            {
                return vsLangObjectNodes;
            }
        }
 protected static void AddCheckBoxToPreviewNode(PreviewChangesNode previewNode, bool setCheckState, bool check)
 {
     ArgumentValidation.CheckForNullReference(previewNode, "previewNode");
     previewNode.ShowCheckBox = true;
     if (setCheckState)
     {
         if (check)
         {
             previewNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Checked;
         }
         else
         {
             previewNode.CheckState = __PREVIEWCHANGESITEMCHECKSTATE.PCCS_Unchecked;
         }
     }
 }
        protected static PreviewChangesNode CreatePreviewNode(
            string displayText,
            ushort icon,
            IntPtr imageList,
            TextChangeProposal proposal,
            bool forceSelection,
            bool enableChangeUncheck,
            bool isChecked)
        {
            var displayData = new VSTREEDISPLAYDATA();

            if (forceSelection)
            {
                Debug.Assert(!string.IsNullOrEmpty(displayText), "display text is null or empty");
                Debug.Assert(proposal != null, "proposal is null");

                var length = displayText.Length;
                displayText = displayText.TrimStart();
                var spaceLength = length - displayText.Length;

                displayData.State = (uint)_VSTREEDISPLAYSTATE.TDS_FORCESELECT;
                displayData.ForceSelectStart = (ushort)(proposal.StartColumn - spaceLength);
                displayData.ForceSelectLength = (ushort)(proposal.EndColumn - proposal.StartColumn);
            }

            if (imageList != IntPtr.Zero)
            {
                displayData.hImageList = imageList;
            }

            displayData.Image = displayData.SelectedImage = icon;

            var node = new PreviewChangesNode(displayText, displayData, displayText, null, proposal);

            if (enableChangeUncheck)
            {
                AddCheckBoxToPreviewNode(node, true, isChecked);
            }

            return node;
        }
        /// <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));
            }
        }
        /// <summary>
        ///     Add child node to this node.
        /// </summary>
        /// <param name="node"></param>
        public void AddChildNode(PreviewChangesNode node)
        {
            if (_childList == null)
            {
                _childList = new List<PreviewChangesNode>();
            }
            node._parent = this;
            _childList.Add(node);

            ComputeCheckedState();
        }