-
Notifications
You must be signed in to change notification settings - Fork 354
Provide ability to add project references #1318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,7 +63,8 @@ internal abstract partial class ProjectNode : HierarchyNode, | |
| IBuildDependencyUpdate, | ||
| IVsProjectSpecialFiles, | ||
| IVsProjectBuildSystem, | ||
| IOleCommandTarget { | ||
| IOleCommandTarget, | ||
| IVsReferenceManagerUser { | ||
| #region nested types | ||
|
|
||
| #if DEV14_OR_LATER | ||
|
|
@@ -1383,71 +1384,191 @@ public virtual VSADDRESULT RunWizard(HierarchyNode parentNode, string itemName, | |
| } | ||
|
|
||
| /// <summary> | ||
| /// This overrides the base class method to show the VS 2005 style Add reference dialog. The ProjectNode implementation | ||
| /// shows the VS 2003 style Add Reference dialog. | ||
| /// Shows the Add Reference dialog. | ||
| /// </summary> | ||
| /// <returns>S_OK if succeeded. Failure other wise</returns> | ||
| public virtual int AddProjectReference() { | ||
| IVsComponentSelectorDlg2 componentDialog; | ||
| Guid guidEmpty = Guid.Empty; | ||
| VSCOMPONENTSELECTORTABINIT[] tabInit = new VSCOMPONENTSELECTORTABINIT[4]; | ||
| string strBrowseLocations = Path.GetDirectoryName(ProjectHome); | ||
| /// <returns>S_OK if succeeded. Failure otherwise</returns> | ||
| public int AddProjectReference() { | ||
| var referenceManager = this.GetService(typeof(SVsReferenceManager)) as IVsReferenceManager; | ||
| if (referenceManager != null) { | ||
| var contextGuids = new[] { | ||
| VSConstants.ProjectReferenceProvider_Guid, | ||
| VSConstants.FileReferenceProvider_Guid | ||
| }; | ||
| referenceManager.ShowReferenceManager( | ||
| this, | ||
| SR.GetString(SR.AddReferenceDialogTitle), | ||
| "VS.ReferenceManager", | ||
| contextGuids.First(), | ||
| false); | ||
| return VSConstants.S_OK; | ||
| } else { | ||
| return VSConstants.E_NOINTERFACE; | ||
| } | ||
| } | ||
|
|
||
| //Add the Project page | ||
| tabInit[0].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT)); | ||
| // Tell the Add Reference dialog to call hierarchies GetProperty with the following | ||
| // propID to enable filtering out ourself from the Project to Project reference | ||
| tabInit[0].varTabInitInfo = (int)__VSHPROPID.VSHPROPID_ShowProjInSolutionPage; | ||
| tabInit[0].guidTab = VSConstants.GUID_SolutionPage; | ||
| #region IVsReferenceManagerUser Members | ||
|
|
||
| // Add the Browse for file page | ||
| tabInit[1].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT)); | ||
| tabInit[1].guidTab = VSConstants.GUID_COMPlusPage; | ||
| tabInit[1].varTabInitInfo = 0; | ||
| void IVsReferenceManagerUser.ChangeReferences(uint operation, IVsReferenceProviderContext changedContext) { | ||
| var op = (__VSREFERENCECHANGEOPERATION)operation; | ||
| __VSREFERENCECHANGEOPERATIONRESULT result; | ||
|
|
||
| // Add the Browse for file page | ||
| tabInit[2].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT)); | ||
| tabInit[2].guidTab = VSConstants.GUID_BrowseFilePage; | ||
| tabInit[2].varTabInitInfo = 0; | ||
| try { | ||
| if (op == __VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD) { | ||
| result = this.AddReferences(changedContext); | ||
| } else { | ||
| result = this.RemoveReferences(changedContext); | ||
| } | ||
| } catch (InvalidOperationException e) { | ||
| Debug.Fail(e.ToString()); | ||
| result = __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_DENY; | ||
| } | ||
|
|
||
| // Add the WebPI page | ||
| tabInit[3].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT)); | ||
| tabInit[3].guidTab = typeof(WebPiComponentPickerControl).GUID; | ||
| tabInit[3].varTabInitInfo = 0; | ||
| if (result == __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_DENY) { | ||
| throw new InvalidOperationException(); | ||
| } | ||
| } | ||
|
|
||
| uint pX = 0, pY = 0; | ||
| Array IVsReferenceManagerUser.GetProviderContexts() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this should call into a protected virtual version of this so subclasses can customize the available providers |
||
| return this.GetProviderContexts(); | ||
| } | ||
|
|
||
| componentDialog = GetService(typeof(SVsComponentSelectorDlg)) as IVsComponentSelectorDlg2; | ||
| try { | ||
| // call the container to open the add reference dialog. | ||
| if (componentDialog != null) { | ||
| // Let the project know not to show itself in the Add Project Reference Dialog page | ||
| ShowProjectInSolutionPage = false; | ||
|
|
||
| // call the container to open the add reference dialog. | ||
| ErrorHandler.ThrowOnFailure(componentDialog.ComponentSelectorDlg2( | ||
| (System.UInt32)(__VSCOMPSELFLAGS.VSCOMSEL_MultiSelectMode | __VSCOMPSELFLAGS.VSCOMSEL_IgnoreMachineName), | ||
| (IVsComponentUser)this, | ||
| 0, | ||
| null, | ||
| SR.GetString(SR.AddReferenceDialogTitle), // Title | ||
| "VS.AddReference", // Help topic | ||
| ref pX, | ||
| ref pY, | ||
| (uint)tabInit.Length, | ||
| tabInit, | ||
| ref guidEmpty, | ||
| AddReferenceExtensions.Replace('|', '\0') + "\0", | ||
| ref strBrowseLocations)); | ||
| } | ||
| } catch (COMException e) { | ||
| Trace.WriteLine("Exception : " + e.Message); | ||
| return e.ErrorCode; | ||
| } finally { | ||
| // Let the project know it can show itself in the Add Project Reference Dialog page | ||
| ShowProjectInSolutionPage = true; | ||
| #endregion | ||
|
|
||
| protected virtual Array GetProviderContexts() { | ||
| var referenceManager = this.GetService(typeof(SVsReferenceManager)) as IVsReferenceManager; | ||
|
|
||
| var contextProviders = new[] { | ||
| CreateProjectReferenceProviderContext(referenceManager), | ||
| CreateFileReferenceProviderContext(referenceManager), | ||
| }; | ||
|
|
||
| return contextProviders; | ||
| } | ||
|
|
||
| private IVsReferenceProviderContext CreateProjectReferenceProviderContext(IVsReferenceManager mgr) { | ||
| var context = mgr.CreateProviderContext(VSConstants.ProjectReferenceProvider_Guid) as IVsProjectReferenceProviderContext; | ||
| context.CurrentProject = this; | ||
|
|
||
| var referenceContainer = this.GetReferenceContainer(); | ||
| var references = referenceContainer | ||
| .EnumReferences() | ||
| .OfType<ProjectReferenceNode>(); | ||
| foreach (var reference in references) { | ||
| var newReference = context.CreateReference() as IVsProjectReference; | ||
| newReference.Identity = reference.ReferencedProjectGuid.ToString("B"); | ||
| } | ||
| return VSConstants.S_OK; | ||
|
|
||
| return context as IVsReferenceProviderContext; | ||
| } | ||
|
|
||
| private IVsReferenceProviderContext CreateFileReferenceProviderContext(IVsReferenceManager mgr) { | ||
| var context = mgr.CreateProviderContext(VSConstants.FileReferenceProvider_Guid) as IVsFileReferenceProviderContext; | ||
|
|
||
| context.BrowseFilter = AddReferenceExtensions.Replace('|', '\0') + "\0"; | ||
| return context as IVsReferenceProviderContext; | ||
| } | ||
|
|
||
| private __VSREFERENCECHANGEOPERATIONRESULT AddReferences(IVsReferenceProviderContext context) { | ||
| var addedReferences = this.GetAddedReferences(context); | ||
|
|
||
| var referenceContainer = this.GetReferenceContainer(); | ||
| foreach (var selectorData in addedReferences) { | ||
| referenceContainer.AddReferenceFromSelectorData(selectorData); | ||
| } | ||
|
|
||
| return __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_ALLOW; | ||
| } | ||
|
|
||
| protected virtual IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsReferenceProviderContext context) { | ||
| var addedReferences = Enumerable.Empty<VSCOMPONENTSELECTORDATA>(); | ||
|
|
||
| if (context.ProviderGuid == VSConstants.ProjectReferenceProvider_Guid) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These if checks should also be pulled into a protected virtual so that derived implementations can check for additional provider guids and then call the base class for the defaults |
||
| addedReferences = GetAddedReferences(context as IVsProjectReferenceProviderContext); | ||
| } | ||
| else if (context.ProviderGuid == VSConstants.FileReferenceProvider_Guid) { | ||
| addedReferences = GetAddedReferences(context as IVsFileReferenceProviderContext); | ||
| } | ||
|
|
||
| return addedReferences; | ||
| } | ||
|
|
||
| private __VSREFERENCECHANGEOPERATIONRESULT RemoveReferences(IVsReferenceProviderContext context) { | ||
| var removedReferences = this.GetRemovedReferences(context); | ||
|
|
||
| foreach (var refNode in removedReferences) { | ||
| refNode.Remove(true /* delete from storage*/); | ||
| } | ||
|
|
||
| return __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_ALLOW; | ||
| } | ||
|
|
||
| protected virtual IEnumerable<ReferenceNode> GetRemovedReferences(IVsReferenceProviderContext context) { | ||
| var removedReferences = Enumerable.Empty<ReferenceNode>(); | ||
|
|
||
| if (context.ProviderGuid == VSConstants.ProjectReferenceProvider_Guid) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ditto on protected virtual |
||
| removedReferences = GetRemovedReferences(context as IVsProjectReferenceProviderContext); | ||
| } | ||
| else if (context.ProviderGuid == VSConstants.FileReferenceProvider_Guid) { | ||
| removedReferences = GetRemovedReferences(context as IVsFileReferenceProviderContext); | ||
| } | ||
|
|
||
| return removedReferences; | ||
| } | ||
|
|
||
| private IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsProjectReferenceProviderContext context) { | ||
| var selectedReferences = context | ||
| .References | ||
| .OfType<IVsProjectReference>() | ||
| .Select(reference => new VSCOMPONENTSELECTORDATA() { | ||
| type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project, | ||
| bstrTitle = reference.Name, | ||
| bstrFile = new FileInfo(reference.FullPath).Directory.FullName, | ||
| bstrProjRef = reference.ReferenceSpecification, | ||
| }); | ||
|
|
||
| return selectedReferences; | ||
| } | ||
|
|
||
| private IEnumerable<ReferenceNode> GetRemovedReferences(IVsProjectReferenceProviderContext context) { | ||
| var selectedReferences = context | ||
| .References | ||
| .OfType<IVsProjectReference>() | ||
| .Select(asmRef => new Guid(asmRef.Identity)); | ||
|
|
||
| var referenceContainer = this.GetReferenceContainer(); | ||
| var references = referenceContainer | ||
| .EnumReferences() | ||
| .OfType<ProjectReferenceNode>() | ||
| .Where(refNode => selectedReferences.Contains(refNode.ReferencedProjectGuid)); | ||
|
|
||
| return references; | ||
| } | ||
|
|
||
| private IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsFileReferenceProviderContext context) { | ||
| var selectedReferences = context | ||
| .References | ||
| .OfType<IVsFileReference>() | ||
| .Select(reference => new VSCOMPONENTSELECTORDATA() { | ||
| type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_File, | ||
| bstrFile = reference.FullPath, | ||
| }); | ||
|
|
||
| return selectedReferences; | ||
| } | ||
|
|
||
| private IEnumerable<ReferenceNode> GetRemovedReferences(IVsFileReferenceProviderContext context) { | ||
| var selectedReferences = context | ||
| .References | ||
| .OfType<IVsFileReference>() | ||
| .Select(fileRef => fileRef.FullPath); | ||
|
|
||
| var referenceContainer = this.GetReferenceContainer(); | ||
| var references = referenceContainer | ||
| .EnumReferences() | ||
| .OfType<ReferenceNode>() | ||
| .Where(refNode => selectedReferences.Contains(refNode.Url)); | ||
|
|
||
| return references; | ||
| } | ||
|
|
||
| protected virtual string AddReferenceExtensions { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way to keep port the WebPI component picker over and keep it present?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed offline, I'll keep WebPI out for this commit