/// <summary> /// Removes a node from the hierarchy. /// </summary> /// <param name="node">The node to remove.</param> public override void RemoveChild(HierarchyNode node) { if (node is MultiverseInterfaceXmlFileNode || node is MultiverseInterfacePythonFileNode) { IPythonLanguageService languageService = (IPythonLanguageService)this.GetService(typeof(IPythonLanguageService)); if (languageService != null) { if (node is MultiverseInterfaceXmlFileNode) { languageService.RemoveFrameXmlFile(node.GetMkDocument()); } if (node is MultiverseInterfacePythonFileNode) { languageService.RemovePythonFile(node.GetMkDocument()); } } } base.RemoveChild(node); }
internal static FileNode AddFile(ProjectNode project, string fileNameWithoutExtension, string extension) { string newModelFilePath = TestUtils.GetNewFileName(project.ProjectFolder, fileNameWithoutExtension, extension); VSADDRESULT[] result = new VSADDRESULT[1]; project.AddItem(VSConstants.VSITEMID_ROOT, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, String.Empty, 1, new string[] { newModelFilePath }, IntPtr.Zero, result); string fileName = Path.GetFileName(newModelFilePath); for (HierarchyNode n = project.FirstChild; n != null; n = n.NextSibling) { if (n is FileNode) { string nodeFileName = Path.GetFileName(n.GetMkDocument()); if (nodeFileName == fileName) { return(n as FileNode); } } } return(null); }
/// <summary> /// Invokes the specified generator /// </summary> /// <param name="fileNode">The node on which to invoke the generator.</param> protected internal virtual void InvokeGenerator(FileNode fileNode) { if (fileNode == null) { throw new ArgumentNullException("fileNode"); } SingleFileGeneratorNodeProperties nodeproperties = fileNode.NodeProperties as SingleFileGeneratorNodeProperties; if (nodeproperties == null) { throw new InvalidOperationException(); } string customToolProgID = nodeproperties.CustomTool; if (string.IsNullOrEmpty(customToolProgID)) { return; } string customToolNamespace = nodeproperties.CustomToolNamespace; try { if (!this.runningGenerator) { //Get the buffer contents for the current node string moniker = fileNode.GetMkDocument(); this.runningGenerator = true; //Get the generator IVsSingleFileGenerator generator; int generateDesignTimeSource; int generateSharedDesignTimeSource; int generateTempPE; SingleFileGeneratorFactory factory = new SingleFileGeneratorFactory(this.projectMgr.ProjectGuid, this.projectMgr.Site); ErrorHandler.ThrowOnFailure(factory.CreateGeneratorInstance(customToolProgID, out generateDesignTimeSource, out generateSharedDesignTimeSource, out generateTempPE, out generator)); //Check to see if the generator supports siting IObjectWithSite objWithSite = generator as IObjectWithSite; if (objWithSite != null) { objWithSite.SetSite(fileNode.OleServiceProvider); } //Determine the namespace if (string.IsNullOrEmpty(customToolNamespace)) { customToolNamespace = this.ComputeNamespace(moniker); } //Run the generator IntPtr[] output = new IntPtr[1]; output[0] = IntPtr.Zero; uint outPutSize; string extension; ErrorHandler.ThrowOnFailure(generator.DefaultExtension(out extension)); //Find if any dependent node exists string dependentNodeName = Path.GetFileNameWithoutExtension(fileNode.FileName) + extension; HierarchyNode dependentNode = fileNode.FirstChild; while (dependentNode != null) { if (string.Compare(dependentNode.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon), fileNode.FileName, StringComparison.OrdinalIgnoreCase) == 0) { dependentNodeName = ((FileNode)dependentNode).FileName; break; } dependentNode = dependentNode.NextSibling; } //If you found a dependent node. if (dependentNode != null) { //Then check out the node and dependent node from SCC if (!this.CanEditFile(dependentNode.GetMkDocument())) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } else //It is a new node to be added to the project { // Check out the project file if necessary. if (!this.projectMgr.QueryEditProjectFile(false)) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } IVsTextStream stream; string inputFileContents = this.GetBufferContents(moniker, out stream); ErrorHandler.ThrowOnFailure(generator.Generate(moniker, inputFileContents, customToolNamespace, output, out outPutSize, this)); byte[] data = new byte[outPutSize]; if (output[0] != IntPtr.Zero) { Marshal.Copy(output[0], data, 0, (int)outPutSize); Marshal.FreeCoTaskMem(output[0]); } //Todo - Create a file and add it to the Project this.UpdateGeneratedCodeFile(fileNode, data, (int)outPutSize, dependentNodeName); } } finally { this.runningGenerator = false; } }
/// <summary> /// This is used to recursively add a folder from an other project. /// Note that while we copy the folder content completely, we only /// add to the project items which are part of the source project. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> protected internal virtual void AddFolderFromOtherProject(string folderToAdd, HierarchyNode targetNode) { if (String.IsNullOrEmpty(folderToAdd)) { throw new ArgumentNullException("folderToAdd"); } if (targetNode == null) { throw new ArgumentNullException("targetNode"); } // Split the reference in its 3 parts int index1 = Guid.Empty.ToString("B").Length; if (index1 + 1 >= folderToAdd.Length) { throw new ArgumentException("folderToAdd"); } // Get the Guid string guidString = folderToAdd.Substring(1, index1 - 2); Guid projectInstanceGuid = new Guid(guidString); // Get the project path int index2 = folderToAdd.IndexOf('|', index1 + 1); if (index2 < 0 || index2 + 1 >= folderToAdd.Length) { throw new ArgumentException("folderToAdd"); } // Finally get the source path string folder = folderToAdd.Substring(index2 + 1); // Get the target path string folderName = Path.GetFileName(Path.GetDirectoryName(folder)); string targetPath = Path.Combine(GetBaseDirectoryForAddingFiles(targetNode), folderName); // Recursively copy the directory to the new location Utilities.RecursivelyCopyDirectory(folder, targetPath); // Retrieve the project from which the items are being copied IVsHierarchy sourceHierarchy; IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution)); ErrorHandler.ThrowOnFailure(solution.GetProjectOfGuid(ref projectInstanceGuid, out sourceHierarchy)); // Then retrieve the item ID of the item to copy uint itemID = VSConstants.VSITEMID_ROOT; ErrorHandler.ThrowOnFailure(sourceHierarchy.ParseCanonicalName(folder, out itemID)); // Ensure we don't end up in an endless recursion if (Utilities.IsSameComObject(this, sourceHierarchy)) { HierarchyNode cursorNode = targetNode; while (cursorNode != null) { if (String.Compare(folder, cursorNode.GetMkDocument(), StringComparison.OrdinalIgnoreCase) == 0) { throw new ApplicationException(); } cursorNode = cursorNode.Parent; } } // Now walk the source project hierarchy to see which node needs to be added. WalkSourceProjectAndAdd(sourceHierarchy, itemID, targetNode, false); }
/// <summary> /// This is used to recursively add a folder from an other project. /// Note that while we copy the folder content completely, we only /// add to the project items which are part of the source project. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> protected internal virtual bool AddFolderFromOtherProject(string folderToAdd, HierarchyNode targetNode, bool drop) { Utilities.ArgumentNotNullOrEmpty(folderToAdd, "folderToAdd"); Utilities.ArgumentNotNull("targetNode", targetNode); var targetFolderNode = targetNode.GetDragTargetHandlerNode(); // Split the reference in its 3 parts int index1 = Guid.Empty.ToString("B").Length; if (index1 + 1 >= folderToAdd.Length) throw new ArgumentOutOfRangeException("folderToAdd"); // Get the Guid string guidString = folderToAdd.Substring(1, index1 - 2); Guid projectInstanceGuid = new Guid(guidString); // Get the project path int index2 = folderToAdd.IndexOf('|', index1 + 1); if (index2 < 0 || index2 + 1 >= folderToAdd.Length) throw new ArgumentOutOfRangeException("folderToAdd"); // Finally get the source path string folder = folderToAdd.Substring(index2 + 1); // Get the target path string folderName = Path.GetFileName(Path.GetDirectoryName(folder)); string targetPath = Path.Combine(GetBaseDirectoryForAddingFiles(targetFolderNode), folderName); // Retrieve the project from which the items are being copied IVsHierarchy sourceHierarchy; IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution)); ErrorHandler.ThrowOnFailure(solution.GetProjectOfGuid(ref projectInstanceGuid, out sourceHierarchy)); // Then retrieve the item ID of the item to copy uint itemID = VSConstants.VSITEMID_ROOT; ErrorHandler.ThrowOnFailure(sourceHierarchy.ParseCanonicalName(folder, out itemID)); string name = folderName; // Ensure we don't end up in an endless recursion if (Utilities.IsSameComObject(this, sourceHierarchy)) { // copy file onto its self, we should make a copy of the folder if (String.Equals(folder, targetNode.GetMkDocument(), StringComparison.OrdinalIgnoreCase)) { if (drop) { // cancelled drag and drop return false; } string newDir; string baseName = folder; folder = CommonUtils.TrimEndSeparator(folder); int copyCount = 0; do { name = folderName + " - Copy"; if (copyCount != 0) { name += " (" + copyCount + ")"; } copyCount++; newDir = Path.Combine(Path.GetDirectoryName(folder), name); } while (Directory.Exists(newDir)); targetPath = newDir; targetFolderNode = targetNode.Parent; } else { HierarchyNode cursorNode = targetFolderNode; while (cursorNode != null) { if (String.Equals(folder, cursorNode.GetMkDocument(), StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException(String.Format("Cannot copy '{0}'. The destination folder is a subfolder of the source folder.", folderName)); } cursorNode = cursorNode.Parent; } } } // Recursively copy the directory to the new location Utilities.RecursivelyCopyDirectory(folder, targetPath); // Now walk the source project hierarchy to see which node needs to be added. WalkSourceProjectAndAdd(sourceHierarchy, itemID, targetFolderNode, false, name); return true; }
protected internal virtual void InvokeGeneratorEx(FileNode fileNode, String document, bool runEvenIfNotDirty) { base.InvokeGenerator(fileNode); Utilities.ArgumentNotNull("fileNode", fileNode); SingleFileGeneratorNodeProperties nodeproperties = fileNode.NodeProperties as SingleFileGeneratorNodeProperties; if (nodeproperties == null) { throw new InvalidOperationException(); } string customToolProgID = nodeproperties.CustomTool; if (string.IsNullOrEmpty(customToolProgID)) { return; } // not sure what to do if BuildAction is set to "MSBuild:Compile". IronPython doesn't handle this correctly either. // This build action is set for .xaml files but doing nothing doesn't seem to cause problems, so for now we ignore this // generator type and do nothing too. If we don't do this, we get lots of message boxes when the clsid of this non-existent // single file generator isn't found. // We should try to find out what the proper action is here. There is no "MSBuild:Compile" entry in the registry // for the C# or VB project system single file generators, so there must be some special handling for this build type // otherwise it would just be blank. Naturally, the IronPython sample isn't any help here. if (customToolProgID.StartsWith("MSBuild:Compile", StringComparison.OrdinalIgnoreCase)) { var project = fileNode.ProjectMgr as XSharpProjectNode; if (project.IsXamlFile(document)) { // need to generate the .g.prg file. project.Build(project.CurrentConfig.ConfigCanonicalName, "BuildGenerateSources"); // BuildGenerateSources } // The C# project system then calls a InvokeMsBuild method with the following contents /* * HRESULT CVsProjBaseFileNode::InvokeMSBuildTarget(_In_z_ LPCWSTR wszMSBuildTarget) * { * HRESULT hr = NOERROR; * * if (wszMSBuildTarget != NULL) * { * CLangBuildMgr *pBuildMgr = GetProject()->GetBuildMgr(); * CComPtr<MSBuildEngine::IProject> srpMSBuildProject = pBuildMgr->GetMSBuildProject(); * * if (CXMakeHelper::DoesTargetExist(srpMSBuildProject, wszMSBuildTarget) && pBuildMgr->HasPassedSecurityChecks()) * { * // Initialize the build engine for this project and configuration. * CSmartMSBuildInitializer smsbi; * CLangProjectConfig *pProjConfig = pBuildMgr->GetConfigs()->GetActiveConfig(); * hr = smsbi.Initialize(pBuildMgr, pProjConfig); * * if (SUCCEEDED(hr)) * { * // Build the specified target in the MSBuild project. * hr = pBuildMgr->BuildTarget(wszMSBuildTarget); * } * * // Don't bother keeping the return value here--we want to * // return failure from Initialize or BuildTarget instead. * smsbi.Restore(pBuildMgr); * } * } * * return hr; * } */ return; } string customToolNamespace = nodeproperties.CustomToolNamespace; try { if (!this.runningGenerator) { //Find if any dependent node exists string dependentNodeName = null; HierarchyNode dependentNode = fileNode.FirstChild; while (dependentNode != null) { string dependentUpon = dependentNode.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon); if (!String.IsNullOrEmpty(dependentUpon)) { if (!Path.IsPathRooted(dependentUpon)) { dependentUpon = Path.Combine(Path.GetDirectoryName(fileNode.Url), dependentUpon); } if (string.Compare(dependentUpon, fileNode.Url, StringComparison.OrdinalIgnoreCase) == 0) { dependentNodeName = ((FileNode)dependentNode).FileName; break; } } dependentNode = dependentNode.NextSibling; } bool outputOutOfDate = dependentNodeName == null; if ((!runEvenIfNotDirty) && !outputOutOfDate) { string generatedFile = Path.Combine(Path.GetDirectoryName(fileNode.GetMkDocument()), dependentNodeName); outputOutOfDate = !File.Exists(generatedFile); if (!outputOutOfDate) { outputOutOfDate = File.GetLastWriteTime(fileNode.GetMkDocument()) > File.GetLastWriteTime(generatedFile); if (!outputOutOfDate) { IVsHierarchy rdtHier; IVsPersistDocData perDocData; uint cookie; outputOutOfDate = this.VerifyFileDirtyInRdt(document, out rdtHier, out perDocData, out cookie); } } } //if (runEvenIfNotDirty || outputOutOfDate) { //Get the buffer contents for the current node string moniker = fileNode.GetMkDocument(); this.runningGenerator = true; anyGeneratorsRunning++; //Get the generator IVsSingleFileGenerator generator; int generateDesignTimeSource; int generateSharedDesignTimeSource; int generateTempPE; SingleFileGeneratorFactory factory = new SingleFileGeneratorFactory(this.ProjectMgr.ProjectGuid, this.ProjectMgr.Site); ErrorHandler.ThrowOnFailure(factory.CreateGeneratorInstance(customToolProgID, out generateDesignTimeSource, out generateSharedDesignTimeSource, out generateTempPE, out generator)); //Check to see if the generator supports siting IObjectWithSite objWithSite = generator as IObjectWithSite; if (objWithSite != null) { objWithSite.SetSite(fileNode.OleServiceProvider); } //Determine the namespace if (string.IsNullOrEmpty(customToolNamespace)) { customToolNamespace = this.ComputeNamespace(moniker); } //Run the generator IntPtr[] output = new IntPtr[1]; output[0] = IntPtr.Zero; uint outPutSize; if (dependentNodeName == null) { string extension = null; try { generator.DefaultExtension(out extension); } catch (Exception e) { if (System.Diagnostics.Debugger.IsAttached) { Debug.WriteLine(e); } } if (!String.IsNullOrEmpty(extension)) { dependentNodeName = Path.GetFileNameWithoutExtension(fileNode.FileName) + extension; } else { dependentNodeName = fileNode.FileName; } } //If you found a dependent node. if (dependentNode != null) { //Then check out the node and dependent node from SCC if (!this.CanEditFile(dependentNode.GetMkDocument())) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } else //It is a new node to be added to the project { // Check out the project file if necessary. if (!this.ProjectMgr.QueryEditProjectFile(false)) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } IVsTextStream stream; string inputFileContents = this.GetBufferContents(moniker, out stream); var res = generator.Generate(moniker, inputFileContents, customToolNamespace, output, out outPutSize, this); byte[] data = new byte[outPutSize]; if (output[0] != IntPtr.Zero) { Marshal.Copy(output[0], data, 0, (int)outPutSize); Marshal.FreeCoTaskMem(output[0]); } //Todo - Create a file and add it to the Project string fileToAdd = this.UpdateGeneratedCodeFile(fileNode, data, (int)outPutSize, dependentNodeName, dependentNode); } } } finally { this.runningGenerator = false; anyGeneratorsRunning--; } }
/// <summary> /// Invokes the specified generator /// </summary> /// <param name="fileNode">The node on which to invoke the generator.</param> protected internal virtual void InvokeGenerator(FileNode fileNode) { if (fileNode == null) { throw new ArgumentNullException("fileNode"); } SingleFileGeneratorNodeProperties nodeproperties = fileNode.NodeProperties as SingleFileGeneratorNodeProperties; if (nodeproperties == null) { throw new InvalidOperationException(); } string customToolProgID = nodeproperties.CustomTool; if (String.IsNullOrEmpty(customToolProgID)) { return; } string customToolNamespace = nodeproperties.CustomToolNamespace; try { ThreadHelper.ThrowIfNotOnUIThread(); if (!this.runningGenerator) { //Get the buffer contents for the current node string moniker = fileNode.GetMkDocument(); this.runningGenerator = true; //Get the generator IVsSingleFileGenerator generator; int generateDesignTimeSource; int generateSharedDesignTimeSource; int generateTempPE; SingleFileGeneratorFactory factory = new SingleFileGeneratorFactory(this.projectMgr.ProjectGuid, this.projectMgr.Site); ErrorHandler.ThrowOnFailure(factory.CreateGeneratorInstance(customToolProgID, out generateDesignTimeSource, out generateSharedDesignTimeSource, out generateTempPE, out generator)); //Check to see if the generator supports siting IObjectWithSite objWithSite = generator as IObjectWithSite; if (objWithSite != null) { objWithSite.SetSite(fileNode.OleServiceProvider); } //Determine the namespace if (String.IsNullOrEmpty(customToolNamespace)) { customToolNamespace = this.ComputeNamespace(moniker); } //Run the generator IntPtr[] output = new IntPtr[1]; output[0] = IntPtr.Zero; uint outPutSize = 0; string extension = String.Empty; try { ErrorHandler.ThrowOnFailure(generator.DefaultExtension(out extension)); } catch (Exception e) { if (System.Diagnostics.Debugger.IsAttached) { Debug.WriteLine("generator.DefaultExtension failed: " + e.Message); } } // IVsTextStream stream; string inputFileContents = this.GetBufferContents(moniker, out stream); // // HACK To support T4 Template // //bool utf8 = false; if (String.Compare(Path.GetExtension(fileNode.FileName), ".tt", true) == 0) { // Per default, for a T4 template, convert to UTF8 // utf8 = true; ? to be done ?? // The Output Extension may be modified by the Template. Check it Regex t4ParsingRegex = new Regex("output.*\\sextension\\s*=\\s*\"(?<pvalue>.*?)(?<=[^\\\\](\\\\\\\\)*)\"", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.ExplicitCapture); MatchCollection matchs = t4ParsingRegex.Matches(inputFileContents); if (matchs.Count > 0) { Match match = matchs[0]; Group group = match.Groups["pvalue"]; extension = group.Value; } // Any Encoding in the Template ? t4ParsingRegex = new Regex("output.*\\sencoding\\s*=\\s*\"(?<pvalue>.*?)(?<=[^\\\\](\\\\\\\\)*)\"", RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.ExplicitCapture); matchs = t4ParsingRegex.Matches(inputFileContents); if (matchs.Count > 0) { Match match = matchs[0]; Group group = match.Groups["pvalue"]; //utf8 = false; } } //Find if any dependent node exists string dependentNodeName = Path.GetFileNameWithoutExtension(fileNode.FileName) + extension; HierarchyNode dependentNode = fileNode.FirstChild; while (dependentNode != null) { if (String.Compare(dependentNode.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon), fileNode.FileName, StringComparison.OrdinalIgnoreCase) == 0) { dependentNodeName = ((FileNode)dependentNode).FileName; break; } dependentNode = dependentNode.NextSibling; } //If you found a dependent node. if (dependentNode != null) { //Then check out the node and dependent node from SCC if (!this.CanEditFile(dependentNode.GetMkDocument())) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } else //It is a new node to be added to the project { // Check out the project file if necessary. if (!this.projectMgr.QueryEditProjectFile(false)) { throw Marshal.GetExceptionForHR(VSConstants.OLE_E_PROMPTSAVECANCELLED); } } try { ErrorHandler.ThrowOnFailure(generator.Generate(moniker, inputFileContents, customToolNamespace, output, out outPutSize, this)); } catch (Exception e) { if (System.Diagnostics.Debugger.IsAttached) { Debug.WriteLine("generator.Generate failed: " + e.Message); } } if (outPutSize > 0) { byte[] data = new byte[outPutSize]; if (output[0] != IntPtr.Zero) { Marshal.Copy(output[0], data, 0, (int)outPutSize); Marshal.FreeCoTaskMem(output[0]); } // HACK T4 Support /* * utf8 = false; * if (utf8) * { * System.Text.StringBuilder sb = new System.Text.StringBuilder(); * sb.Append(System.Text.Encoding.ASCII.GetString(data, 0, (int)outPutSize)); * // * System.Text.Encoding enc = new System.Text.UTF8Encoding(true); * byte[] preamble = enc.GetPreamble(); * byte[] encData = enc.GetBytes(sb.ToString()); * // * outPutSize = (uint)encData.Length + (uint)preamble.Length; * data = new byte[outPutSize]; * Array.Copy(preamble, data, preamble.Length); * Array.Copy(encData, 0, data, preamble.Length, encData.Length); * } */ //Todo - Create a file and add it to the Project string fileToAdd = this.UpdateGeneratedCodeFile(fileNode, data, (int)outPutSize, dependentNodeName); } } } finally { this.runningGenerator = false; } }