Microsoft.VisualStudio.Project.FileNode.AfterSaveItemAs C# (CSharp) Method

AfterSaveItemAs() protected method

Performs a SaveAs operation of an open document. Called from SaveItem after the running document table has been updated with the new doc data.
protected AfterSaveItemAs ( IntPtr docData, string newFilePath ) : int
docData System.IntPtr A pointer to the document in the rdt
newFilePath string The new file path to the document
return int
        protected override int AfterSaveItemAs(IntPtr docData, string newFilePath)
        {
            if(String.IsNullOrEmpty(newFilePath))
            {
                throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "newFilePath");
            }

            int returnCode = VSConstants.S_OK;
            newFilePath = newFilePath.Trim();

            //Identify if Path or FileName are the same for old and new file
            string newDirectoryName = Path.GetDirectoryName(newFilePath);
            Uri newDirectoryUri = new Uri(newDirectoryName);
            string newCanonicalDirectoryName = newDirectoryUri.LocalPath;
            newCanonicalDirectoryName = newCanonicalDirectoryName.TrimEnd(Path.DirectorySeparatorChar);
            string oldCanonicalDirectoryName = new Uri(Path.GetDirectoryName(this.GetMKDocument())).LocalPath;
            oldCanonicalDirectoryName = oldCanonicalDirectoryName.TrimEnd(Path.DirectorySeparatorChar);
            string errorMessage = String.Empty;
            bool isSamePath = NativeMethods.IsSamePath(newCanonicalDirectoryName, oldCanonicalDirectoryName);
            bool isSameFile = NativeMethods.IsSamePath(newFilePath, this.Url);

            string linkPath = null;
            string projectCannonicalDirecoryName = new Uri(this.ProjectManager.ProjectFolder).LocalPath;
            projectCannonicalDirecoryName = projectCannonicalDirecoryName.TrimEnd(Path.DirectorySeparatorChar);
            if(!isSamePath && newCanonicalDirectoryName.IndexOf(projectCannonicalDirecoryName, StringComparison.OrdinalIgnoreCase) == -1)
            {
                // Link the new file into the same location in the project hierarchy it was before.
                string oldRelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Link);
                if (String.IsNullOrEmpty(oldRelPath))
                {
                    oldRelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
                }

                newDirectoryName = Path.GetDirectoryName(oldRelPath);
                linkPath = Path.Combine(newDirectoryName, Path.GetFileName(newFilePath));
            }

            //Get target container
            HierarchyNode targetContainer = null;
            if(isSamePath)
            {
                targetContainer = this.Parent;
            }
            else if(NativeMethods.IsSamePath(newCanonicalDirectoryName, projectCannonicalDirecoryName))
            {
                //the projectnode is the target container
                targetContainer = this.ProjectManager;
            }
            else
            {
                //search for the target container among existing child nodes
                targetContainer = this.ProjectManager.FindChild(newDirectoryName);
                if(targetContainer != null && (targetContainer is FileNode))
                {
                    // We already have a file node with this name in the hierarchy.
                    errorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.FileAlreadyExistsAndCannotBeRenamed, CultureInfo.CurrentUICulture), Path.GetFileNameWithoutExtension(newFilePath));
                    throw new InvalidOperationException(errorMessage);
                }
            }

            if(targetContainer == null)
            {
                // Add a chain of subdirectories to the project.
                string relativeUri = PackageUtilities.GetPathDistance(this.ProjectManager.BaseUri.Uri, newDirectoryUri);
                Debug.Assert(!String.IsNullOrEmpty(relativeUri) && relativeUri != newDirectoryUri.LocalPath, "Could not make pat distance of " + this.ProjectManager.BaseUri.Uri.LocalPath + " and " + newDirectoryUri);
                targetContainer = this.ProjectManager.CreateFolderNodes(relativeUri);
            }
            Debug.Assert(targetContainer != null, "We should have found a target node by now");

            //Suspend file changes while we rename the document
            string oldrelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
            string oldName = Path.Combine(this.ProjectManager.ProjectFolder, oldrelPath);
            SuspendFileChanges sfc = new SuspendFileChanges(this.ProjectManager.Site, oldName);
            sfc.Suspend();

            try
            {
                // Rename the node.
                DocumentManager.UpdateCaption(this.ProjectManager.Site, Path.GetFileName(newFilePath), docData);
                // Check if the file name was actually changed.
                // In same cases (e.g. if the item is a file and the user has changed its encoding) this function
                // is called even if there is no real rename.
                if(!isSameFile || (this.Parent.Id != targetContainer.Id))
                {
                    // The path of the file is changed or its parent is changed; in both cases we have
                    // to rename the item.
                    this.RenameFileNode(oldName, newFilePath, linkPath, targetContainer);
                    this.ItemNode.SetMetadata(ProjectFileConstants.Link, linkPath);
                    OnInvalidateItems(this.Parent);
                }
            }
            catch(Exception e)
            {
                Trace.WriteLine("Exception : " + e.Message);
                this.RecoverFromRenameFailure(newFilePath, oldrelPath);
                throw;
            }
            finally
            {
                sfc.Resume();
            }

            return returnCode;
        }