/// <summary> /// Constructor for the ReferenceNode. It is called when the project is reloaded, when the project element representing the refernce exists. /// </summary> internal ProjectReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.referencedProjectRelativePath = this.ItemNode.GetMetadata(ProjectFileConstants.Include); Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectRelativePath), "Could not retrive referenced project path form project file"); string guidString = this.ItemNode.GetMetadata(ProjectFileConstants.Project); // Continue even if project setttings cannot be read. try { this.referencedProjectGuid = new Guid(guidString); this.buildDependency = new BuildDependency(this.ProjectMgr, this.referencedProjectGuid); this.ProjectMgr.AddBuildDependency(this.buildDependency); } finally { Debug.Assert(this.referencedProjectGuid != Guid.Empty, "Could not retrive referenced project guidproject file"); this.referencedProjectName = this.ItemNode.GetMetadata(ProjectFileConstants.Name); Debug.Assert(!String.IsNullOrEmpty(this.referencedProjectName), "Could not retrive referenced project name form project file"); } Uri uri = new Uri(this.ProjectMgr.BaseURI.Uri, this.referencedProjectRelativePath); if (uri != null) { this.referencedProjectFullPath = Microsoft.VisualStudio.Shell.Url.Unescape(uri.LocalPath, true); } }
/// <summary> /// Constructor for the ComReferenceNode. /// </summary> internal ComReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.typeName = this.ItemNode.GetMetadata(ProjectFileConstants.Include); string typeGuidAsString = this.ItemNode.GetMetadata(ProjectFileConstants.Guid); if (typeGuidAsString != null) { this.typeGuid = new Guid(typeGuidAsString); } this.majorVersionNumber = this.ItemNode.GetMetadata(ProjectFileConstants.VersionMajor); this.minorVersionNumber = this.ItemNode.GetMetadata(ProjectFileConstants.VersionMinor); this.lcid = int.Parse(this.ItemNode.GetMetadata(ProjectFileConstants.Lcid)); this.SetProjectItemsThatRelyOnReferencesToBeResolved(false); this.SetInstalledFilePath(); }
/// <summary> /// This will clone a template project file and add it as a /// subproject to our hierarchy. /// If you want to create a project for which there exist a /// vstemplate, consider using RunVsTemplateWizard instead. /// </summary> /*protected internal, but public for FSharp.Project.dll*/ public virtual NestedProjectNode AddNestedProjectFromTemplate(ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { throw new ArgumentNullException("element"); } string destination = elementToUse.GetFullPathForElement(); string template = this.GetProjectTemplatePath(elementToUse); return this.AddNestedProjectFromTemplate(template, Path.GetDirectoryName(destination), Path.GetFileName(destination), elementToUse, creationFlags); }
/// <summary> /// Constructor for the FolderNode /// </summary> /// <param name="root">Root node of the hierarchy</param> /// <param name="relativePath">relative path from root i.e.: "NewFolder1\\NewFolder2\\NewFolder3</param> /// <param name="element">Associated project element</param> internal FolderNode(ProjectNode root, string relativePath, ProjectElement element) : base(root, element) { this.VirtualNodeName = relativePath.TrimEnd('\\'); }
/// <summary> /// Creates a com reference node from the project element. /// </summary> internal virtual ComReferenceNode CreateComReferenceNode(ProjectElement reference) { return new ComReferenceNode(this.ProjectMgr, reference); }
internal static AssemblyReferenceNode CreateFromProjectFile(ProjectNode root, ProjectElement element, BuildResult buildResult) { return new AssemblyReferenceNode(root, element, buildResult); }
/// <summary> /// Adds references to this container from a MSBuild project. /// </summary> public void LoadReferencesFromBuildProject(Microsoft.Build.Evaluation.Project buildProject) { Build.Execution.ProjectInstance projectInstanceToSearchExpandedReferences = null; // if project uses implicitly expanded list of references, // evaluate ImplicitlyExpandTargetFramework target and collect all resolved 'ReferencePath' items // later we'll group them and create special reference nodes that represent assembly groupings if (ProjectMgr.ImplicitlyExpandTargetFramework) { var res = ProjectMgr.Build(MsBuildTarget.ImplicitlyExpandTargetFramework); if (res.IsSuccessful) { projectInstanceToSearchExpandedReferences = res.ProjectInstance; } } // collect groupled framework references if (projectInstanceToSearchExpandedReferences != null) { // fetch all 'ReferencePath' items that were resolved from implicitly expanded references (metadata#ResolvedFrom = ImplicitlyExpandTargetFramework) var groupings = projectInstanceToSearchExpandedReferences .GetItems(ProjectFileConstants.ReferencePath) .Where(item => string.Equals(item.GetMetadataValue(ProjectFileConstants.ResolvedFrom), MsBuildTarget.ImplicitlyExpandTargetFramework, StringComparison.OrdinalIgnoreCase)) .Select( item => new { referenceGroupingDisplayName = item.GetMetadataValue("ReferenceGroupingDisplayName"), referenceGrouping = item.GetMetadataValue("ReferenceGrouping"), file = item.EvaluatedInclude } ) .Where(r => !string.IsNullOrEmpty(r.referenceGrouping) && !string.IsNullOrEmpty(r.referenceGroupingDisplayName) && !string.IsNullOrEmpty(r.file) && File.Exists(r.file) ) .GroupBy(r => r.referenceGrouping); foreach (var grouping in groupings) { var version = ParseVersionFromReferenceGrouping(grouping.Key); if (version == null) { continue; } // pick property values from the first item - they should be the same for all elements in the grouping var first = grouping.First(); var groupedFiles = grouping.Select(x => x.file).ToArray(); var versonText = string.Format( "{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build != -1 ? version.Build : 0, version.Revision != -1 ? version.Revision : 0 ); var node = new GroupingReferenceNode(ProjectMgr, first.referenceGroupingDisplayName, first.referenceGrouping, Path.GetDirectoryName(first.file), versonText, groupedFiles); AddChild(node); } } BuildResult buildResult = this.ProjectMgr.Build(MsBuildTarget.ResolveAssemblyReferences); foreach (string referenceType in SupportedReferenceTypes) { bool isAssemblyReference = referenceType == ProjectFileConstants.Reference; if (isAssemblyReference && !buildResult.IsSuccessful) { continue; } foreach (var item in MSBuildProject.GetItems(buildProject, referenceType)) { ProjectElement element = new ProjectElement(this.ProjectMgr, item, false); ReferenceNode node = CreateReferenceNode(referenceType, element, buildResult); if (node != null) { this.AddChild(node); } if (isAssemblyReference) { ProjectMgr.UpdateValueOfCanUseTargetFSharpCoreReferencePropertyIfNecessary(node); } } } }
/// <summary> /// Creates a project reference node given an existing project element. /// </summary> internal virtual ProjectReferenceNode CreateProjectReferenceNode(ProjectElement element) { return new ProjectReferenceNode(this.ProjectMgr, element); }
private ProjectElement GetProjectElementBasedOnInputFromComponentSelectorData() { ProjectElement element = new ProjectElement(this.ProjectMgr, this.typeName, ProjectFileConstants.COMReference); // Set the basic information regarding this COM component element.SetMetadata(ProjectFileConstants.Guid, this.typeGuid.ToString("B")); element.SetMetadata(ProjectFileConstants.VersionMajor, this.majorVersionNumber); element.SetMetadata(ProjectFileConstants.VersionMinor, this.minorVersionNumber); element.SetMetadata(ProjectFileConstants.Lcid, this.lcid.ToString()); element.SetMetadata(ProjectFileConstants.Isolated, false.ToString()); // See if a PIA exist for this component TypeLibConverter typelib = new TypeLibConverter(); string assemblyName; string assemblyCodeBase; if (typelib.GetPrimaryInteropAssembly(this.typeGuid, Int32.Parse(this.majorVersionNumber, CultureInfo.InvariantCulture), Int32.Parse(this.minorVersionNumber, CultureInfo.InvariantCulture), this.lcid, out assemblyName, out assemblyCodeBase)) { element.SetMetadata(ProjectFileConstants.WrapperTool, WrapperToolAttributeValue.Primary.ToString().ToLowerInvariant()); } else { // MSBuild will have to generate an interop assembly element.SetMetadata(ProjectFileConstants.WrapperTool, WrapperToolAttributeValue.TlbImp.ToString().ToLowerInvariant()); element.SetMetadata(ProjectFileConstants.Private, true.ToString()); } return element; }
/// <summary> /// Constructor for the DependentFileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> internal DependentFileNode(ProjectNode root, ProjectElement element) : base(root, element) { this.HasParentNodeNameRelation = false; }
/// <summary> /// Get information from the registry based for the project /// factory corresponding to the TypeGuid of the element /// </summary> private RegisteredProjectType GetRegisteredProject(ProjectElement element) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { throw new ArgumentNullException("element"); } // Get the project type guid from project elementToUse string typeGuidString = elementToUse.GetMetadataAndThrow(ProjectFileConstants.TypeGuid, new ApplicationException()); Guid projectFactoryGuid = new Guid(typeGuidString); EnvDTE.DTE dte = this.ProjectMgr.Site.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; Debug.Assert(dte != null, "Could not get the automation object from the services exposed by this project"); if (dte == null) throw new InvalidOperationException(); RegisteredProjectType registeredProjectType = RegisteredProjectType.CreateRegisteredProjectType(projectFactoryGuid); Debug.Assert(registeredProjectType != null, "Could not read the registry setting associated to this project."); if (registeredProjectType == null) { throw new InvalidOperationException(); } return registeredProjectType; }
/// <summary> /// Adds references to this container from a MSBuild project. /// </summary> public void LoadReferencesFromBuildProject(Microsoft.Build.Evaluation.Project buildProject) { Build.Execution.ProjectInstance projectInstanceToSearchExpandedReferences = null; // if project uses implicitly expanded list of references, // evaluate ImplicitlyExpandTargetFramework target and collect all resolved 'ReferencePath' items // later we'll group them and create special reference nodes that represent assembly groupings if (ProjectMgr.ImplicitlyExpandTargetFramework) { var res = ProjectMgr.Build(MsBuildTarget.ImplicitlyExpandTargetFramework); if (res.IsSuccessful) { projectInstanceToSearchExpandedReferences = res.ProjectInstance; } } // collect groupled framework references if (projectInstanceToSearchExpandedReferences != null) { // fetch all 'ReferencePath' items that were resolved from implicitly expanded references (metadata#ResolvedFrom = ImplicitlyExpandTargetFramework) var groupings = projectInstanceToSearchExpandedReferences .GetItems(ProjectFileConstants.ReferencePath) .Where(item => string.Equals(item.GetMetadataValue(ProjectFileConstants.ResolvedFrom), MsBuildTarget.ImplicitlyExpandTargetFramework, StringComparison.OrdinalIgnoreCase)) .Select( item => new { referenceGroupingDisplayName = item.GetMetadataValue("ReferenceGroupingDisplayName"), referenceGrouping = item.GetMetadataValue("ReferenceGrouping"), file = item.EvaluatedInclude } ) .Where(r => !string.IsNullOrEmpty(r.referenceGrouping) && !string.IsNullOrEmpty(r.referenceGroupingDisplayName) && !string.IsNullOrEmpty(r.file) && File.Exists(r.file) ) .GroupBy(r => r.referenceGrouping); foreach (var grouping in groupings) { var version = ParseVersionFromReferenceGrouping(grouping.Key); if (version == null) { continue; } // pick property values from the first item - they should be the same for all elements in the grouping var first = grouping.First(); var groupedFiles = grouping.Select(x => x.file).ToArray(); var versonText = string.Format( "{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build != -1 ? version.Build : 0, version.Revision != -1 ? version.Revision : 0 ); var node = new GroupingReferenceNode(ProjectMgr, first.referenceGroupingDisplayName, first.referenceGrouping, Path.GetDirectoryName(first.file), versonText, groupedFiles); AddChild(node); } } BuildResult buildResult = this.ProjectMgr.Build(MsBuildTarget.ResolveAssemblyReferences); foreach (string referenceType in SupportedReferenceTypes) { bool isAssemblyReference = referenceType == ProjectFileConstants.Reference; if (isAssemblyReference && !buildResult.IsSuccessful) { continue; } foreach (var item in MSBuildProject.GetItems(buildProject, referenceType)) { ProjectElement element = new ProjectElement(this.ProjectMgr, item, false); ReferenceNode node = CreateReferenceNode(referenceType, element, buildResult); if (node != null) { this.AddChild(node); } if (isAssemblyReference) { ProjectMgr.UpdateValueOfCanUseTargetFSharpCoreReferencePropertyIfNecessary(node); } } } }
/// <summary> /// This is used when loading the project to loop through all the items /// and for each SubProject it finds, it create the project and a node /// in our Hierarchy to hold the project. /// </summary> /*internal, but public for FSharp.Project.dll*/ protected void CreateNestedProjectNodes() { // 1. Create a ProjectElement with the found item and then Instantiate a new Nested project with this ProjectElement. // 2. Link into the hierarchy. // Read subprojects from from msbuildmodel __VSCREATEPROJFLAGS creationFlags = __VSCREATEPROJFLAGS.CPF_NOTINSLNEXPLR | __VSCREATEPROJFLAGS.CPF_SILENT; if (this.IsNewProject) { creationFlags |= __VSCREATEPROJFLAGS.CPF_CLONEFILE; } else { creationFlags |= __VSCREATEPROJFLAGS.CPF_OPENFILE; } foreach (Microsoft.Build.Evaluation.ProjectItem item in MSBuildProject.GetItems(this.BuildProject)) { if (String.Compare(MSBuildItem.GetItemType(item), ProjectFileConstants.SubProject, StringComparison.OrdinalIgnoreCase) == 0) { this.nestedProjectElement = new ProjectElement(this, item, false); if (!this.IsNewProject) { AddExistingNestedProject(null, creationFlags); } else { // If we are creating the subproject from a vstemplate/vsz file bool isVsTemplate = Utilities.IsTemplateFile(GetProjectTemplatePath(null)); if (isVsTemplate) { RunVsTemplateWizard(null, true); } else { // We are cloning the specified project file AddNestedProjectFromTemplate(null, creationFlags); } } } } this.nestedProjectElement = null; }
public void RunVsTemplateWizard(ProjectElement element, bool silent) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { throw new ArgumentNullException("element"); } this.nestedProjectElement = elementToUse; Automation.OAProject oaProject = GetAutomationObject() as Automation.OAProject; if (oaProject == null || oaProject.ProjectItems == null) throw new System.InvalidOperationException(SR.GetString(SR.InvalidAutomationObject, CultureInfo.CurrentUICulture)); Debug.Assert(oaProject.Object != null, "The project automation object should have set the Object to the SolutionFolder"); Automation.OASolutionFolder<ProjectContainerNode> folder = oaProject.Object as Automation.OASolutionFolder<ProjectContainerNode>; // Prepare the parameters to pass to RunWizardFile string destination = elementToUse.GetFullPathForElement(); string template = this.GetProjectTemplatePath(elementToUse); object[] wizParams = new object[7]; wizParams[0] = EnvDTE.Constants.vsWizardAddSubProject; wizParams[1] = Path.GetFileNameWithoutExtension(destination); wizParams[2] = oaProject.ProjectItems; wizParams[3] = Path.GetDirectoryName(destination); wizParams[4] = Path.GetFileNameWithoutExtension(destination); wizParams[5] = Path.GetDirectoryName(folder.DTE.FullName); //VS install dir wizParams[6] = silent; IVsDetermineWizardTrust wizardTrust = this.GetService(typeof(SVsDetermineWizardTrust)) as IVsDetermineWizardTrust; if (wizardTrust != null) { Guid guidProjectAdding = Guid.Empty; // In case of a project template an empty guid should be added as the guid parameter. See env\msenv\core\newtree.h IsTrustedTemplate method definition. wizardTrust.OnWizardInitiated(template, ref guidProjectAdding); } try { // Make the call to execute the wizard. This should cause AddNestedProjectFromTemplate to be // called back with the correct set of parameters. EnvDTE.IVsExtensibility extensibilityService = (EnvDTE.IVsExtensibility)GetService(typeof(EnvDTE.IVsExtensibility)); EnvDTE.wizardResult result = extensibilityService.RunWizardFile(template, 0, ref wizParams); if (result == EnvDTE.wizardResult.wizardResultFailure) throw new COMException(); } finally { if (wizardTrust != null) { wizardTrust.OnWizardCompleted(); } } }
/// <summary> /// Based on the Template and TypeGuid properties of the /// element, generate the full template path. /// /// TypeGuid should be the Guid of a registered project factory. /// Template can be a full path, a project template (for projects /// that support VsTemplates) or a relative path (for other projects). /// </summary> /*protected, but public for FSharp.Project.dll*/ public virtual string GetProjectTemplatePath(ProjectElement element) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { throw new ArgumentNullException("element"); } string templateFile = elementToUse.GetMetadata(ProjectFileConstants.Template); Debug.Assert(!String.IsNullOrEmpty(templateFile), "No template file has been specified in the template attribute in the project file"); string fullPath = templateFile; if (!Path.IsPathRooted(templateFile)) { RegisteredProjectType registeredProjectType = this.GetRegisteredProject(elementToUse); // This is not a full path Debug.Assert(registeredProjectType != null && (!String.IsNullOrEmpty(registeredProjectType.DefaultProjectExtensionValue) || !String.IsNullOrEmpty(registeredProjectType.WizardTemplatesDirValue)), " Registered wizard directory value not set in the registry."); // See if this specify a VsTemplate file fullPath = registeredProjectType.GetVsTemplateFile(templateFile); if (String.IsNullOrEmpty(fullPath)) { // Default to using the WizardTemplateDir to calculate the absolute path fullPath = Path.Combine(registeredProjectType.WizardTemplatesDirValue, templateFile); } } return fullPath; }
/// <summary> /// Override this method if you want to provide your own type of nodes. /// This would be the case if you derive a class from NestedProjectNode /// </summary> /*protected, but public for FSharp.Project.dll*/ public virtual NestedProjectNode CreateNestedProjectNode(ProjectElement element) { return new NestedProjectNode(this, element); }
/// <summary> /// This can be called directly or through RunVsTemplateWizard. /// This will clone a template project file and add it as a /// subproject to our hierarchy. /// If you want to create a project for which there exist a /// vstemplate, consider using RunVsTemplateWizard instead. /// </summary> /*protected internal, but public for FSharp.Project.dll*/ public virtual NestedProjectNode AddNestedProjectFromTemplate(string fileName, string destination, string projectName, ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { // If this is project creation and the template specified a subproject in its project file, this.nestedProjectElement will be used ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { // If this is null, this means MSBuild does not know anything about our subproject so add an MSBuild item for it elementToUse = new ProjectElement(this, fileName, ProjectFileConstants.SubProject); } NestedProjectNode node = CreateNestedProjectNode(elementToUse); node.Init(fileName, destination, projectName, creationFlags); // In case that with did not have an existing element, or the nestedProjectelement was null // and since Init computes the final path, set the MSBuild item to that path if (this.nestedProjectElement == null) { string relativePath = node.Url; if (Path.IsPathRooted(relativePath)) { relativePath = this.ProjectFolder; if (!relativePath.EndsWith("/\\", StringComparison.Ordinal)) { relativePath += Path.DirectorySeparatorChar; } relativePath = new Url(relativePath).MakeRelative(new Url(node.Url)); } elementToUse.Rename(relativePath); } this.AddChild(node); return node; }
/// <summary> /// Creates a project reference node given an existing project element. /// </summary> internal virtual ProjectReferenceNode CreateProjectReferenceNode(ProjectElement element) { return(new ProjectReferenceNode(this.ProjectMgr, element)); }
internal ReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.ExcludeNodeFromScc = true; }
/// <summary> /// Creates a com reference node from the project element. /// </summary> internal virtual ComReferenceNode CreateComReferenceNode(ProjectElement reference) { return(new ComReferenceNode(this.ProjectMgr, reference)); }
/// <summary> /// Constructor for the LinkedFileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> /// <param name="hierarchyId">Optional hierarchy id - used during rename</param> internal LinkedFileNode(ProjectNode root, ProjectElement e, uint?hierarchyId = null) : base(root, e, hierarchyId) { this._linkFile = false; }
/// <summary> /// Constructor for the LinkedFileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> /// <param name="hierarchyId">Optional hierarchy id - used during rename</param> internal LinkedFileNode(ProjectNode root, ProjectElement e, uint? hierarchyId = null) : base(root, e, hierarchyId) { this._linkFile = false; }
internal static AssemblyReferenceNode CreateFromProjectFile(ProjectNode root, ProjectElement element, BuildResult buildResult) { return(new AssemblyReferenceNode(root, element, buildResult)); }
internal virtual ReferenceNode CreateReferenceNode(string referenceType, ProjectElement element, BuildResult buildResult) { ReferenceNode node = null; if (referenceType == ProjectFileConstants.COMReference) { node = this.CreateComReferenceNode(element); } else if (referenceType == ProjectFileConstants.Reference) { node = this.CreateAssemblyReferenceNode(element, buildResult); } else if (referenceType == ProjectFileConstants.ProjectReference) { node = this.CreateProjectReferenceNode(element); EnableCachingForProjectReferencesInBatchUpdate(node); } return node; }
/// <summary> /// Creating AssemblyReferenceNode from fsproj element /// </summary> private AssemblyReferenceNode(ProjectNode root, ProjectElement element, BuildResult buildResult) : base(root, element) { BindFromBuildResult(element.Item, buildResult); }
/// <summary> /// Creates an assembly refernce node from a project element. /// </summary> internal virtual AssemblyReferenceNode CreateAssemblyReferenceNode(ProjectElement element, BuildResult buildResult) { AssemblyReferenceNode node = null; try { node = AssemblyReferenceNode.CreateFromProjectFile(this.ProjectMgr, element, buildResult); } catch (ArgumentNullException e) { Trace.WriteLine("Exception : " + e.Message); } catch (FileNotFoundException e) { Trace.WriteLine("Exception : " + e.Message); } catch (BadImageFormatException e) { Trace.WriteLine("Exception : " + e.Message); } catch (FileLoadException e) { Trace.WriteLine("Exception : " + e.Message); } catch (System.Security.SecurityException e) { Trace.WriteLine("Exception : " + e.Message); } return node; }
/// <summary> /// Constructor for the FolderNode /// </summary> /// <param name="root">Root node of the hierarchy</param> /// <param name="relativePath">relative path from root i.e.: "NewFolder1\\NewFolder2\\NewFolder3</param> /// <param name="element">Associated project element</param> internal FolderNode(ProjectNode root, string relativePath, ProjectElement element) : base(root, element) { this.VirtualNodeName = relativePath.TrimEnd('\\'); }
internal ReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.ExcludeNodeFromScc = true; }
/// <summary> /// Constructor for the DependentFileNode /// </summary> /// <param name="root">Root of the hierarchy</param> /// <param name="e">Associated project element</param> internal DependentFileNode(ProjectNode root, ProjectElement element) : base(root, element) { this.HasParentNodeNameRelation = false; }
/// <summary> /// Creating AssemblyReferenceNode from fsproj element /// </summary> private AssemblyReferenceNode(ProjectNode root, ProjectElement element, BuildResult buildResult) : base(root, element) { BindFromBuildResult(element.Item, buildResult); }
/// <summary> /// Add an existing project as a nested node of our hierarchy. /// This is used while loading the project and can also be used /// to add an existing project to our hierarchy. /// </summary> /*protected internal, but public for FSharp.Project.dll*/ public virtual NestedProjectNode AddExistingNestedProject(ProjectElement element, __VSCREATEPROJFLAGS creationFlags) { ProjectElement elementToUse = (element == null) ? this.nestedProjectElement : element; if (elementToUse == null) { throw new ArgumentNullException("element"); } string filename = elementToUse.GetFullPathForElement(); // Delegate to AddNestedProjectFromTemplate. Because we pass flags that specify open project rather then clone, this will works. Debug.Assert((creationFlags & __VSCREATEPROJFLAGS.CPF_OPENFILE) == __VSCREATEPROJFLAGS.CPF_OPENFILE, "__VSCREATEPROJFLAGS.CPF_OPENFILE should have been specified, did you mean to call AddNestedProjectFromTemplate?"); return AddNestedProjectFromTemplate(filename, Path.GetDirectoryName(filename), Path.GetFileName(filename), elementToUse, creationFlags); }