Example #1
0
        /// <summary>
        /// Gets called to rename the eventually running document this hierarchyitem points to
        /// </summary>
        /// returns FALSE if the doc can not be renamed
        internal bool RenameDocument(string oldName, string newName)
        {
            IVsRunningDocumentTable pRDT = this.GetService(typeof(IVsRunningDocumentTable)) as IVsRunningDocumentTable;

            if (pRDT == null)
            {
                return(false);
            }
            IntPtr       docData = IntPtr.Zero;
            IVsHierarchy pIVsHierarchy;
            uint         itemId;
            uint         uiVsDocCookie;

            SuspendFileChanges sfc = null;

            if (File.Exists(oldName))
            {
                sfc = new SuspendFileChanges(this.ProjectMgr.Site, oldName);
                sfc.Suspend();
            }

            try {
                // Suspend ms build since during a rename operation no msbuild re-evaluation should be performed until we have finished.
                // Scenario that could fail if we do not suspend.
                // We have a project system relying on MPF that triggers a Compile target build (re-evaluates itself) whenever the project changes. (example: a file is added, property changed.)
                // 1. User renames a file in  the above project sytem relying on MPF
                // 2. Our rename funstionality implemented in this method removes and readds the file and as a post step copies all msbuild entries from the removed file to the added file.
                // 3. The project system mentioned will trigger an msbuild re-evaluate with the new item, because it was listening to OnItemAdded.
                //    The problem is that the item at the "add" time is only partly added to the project, since the msbuild part has not yet been copied over as mentioned in part 2 of the last step of the rename process.
                //    The result is that the project re-evaluates itself wrongly.
                VSRENAMEFILEFLAGS renameflag = VSRENAMEFILEFLAGS.VSRENAMEFILEFLAGS_NoFlags;
                ErrorHandler.ThrowOnFailure(pRDT.FindAndLockDocument((uint)_VSRDTFLAGS.RDT_NoLock, oldName, out pIVsHierarchy, out itemId, out docData, out uiVsDocCookie));

                if (pIVsHierarchy != null && !Utilities.IsSameComObject(pIVsHierarchy, this.ProjectMgr))
                {
                    // Don't rename it if it wasn't opened by us.
                    return(false);
                }

                // ask other potentially running packages
                if (!this.ProjectMgr.Tracker.CanRenameItem(oldName, newName, renameflag))
                {
                    return(false);
                }

                if (IsFileOnDisk(oldName))
                {
                    RenameInStorage(oldName, newName);
                }

                // For some reason when ignoreFileChanges is called in Resume, we get an ArgumentException because
                // Somewhere a required fileWatcher is null.  This issue only occurs when you copy and rename a typescript file,
                // Calling Resume here prevents said fileWatcher from being null. Don't know why it works, but it does.
                // Also fun! This is the only location it can go (between RenameInStorage and RenameFileNode)
                // So presumably there is some condition that is no longer met once both of these methods are called with a ts file.
                // https://nodejstools.codeplex.com/workitem/1510
                if (sfc != null)
                {
                    sfc.Resume();
                    sfc.Suspend();
                }

                if (!CommonUtils.IsSamePath(oldName, newName))
                {
                    // Check out the project file if necessary.
                    if (!this.ProjectMgr.QueryEditProjectFile(false))
                    {
                        throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED);
                    }

                    this.RenameFileNode(oldName, newName);
                }
                else
                {
                    this.RenameCaseOnlyChange(oldName, newName);
                }

                DocumentManager.UpdateCaption(this.ProjectMgr.Site, Caption, docData);

                // changed from MPFProj:
                // http://mpfproj10.codeplex.com/WorkItem/View.aspx?WorkItemId=8231
                this.ProjectMgr.Tracker.OnItemRenamed(oldName, newName, renameflag);
            } finally {
                if (sfc != null)
                {
                    sfc.Resume();
                }
                if (docData != IntPtr.Zero)
                {
                    Marshal.Release(docData);
                }
            }

            return(true);
        }