Skip to content

Commit 5f7ea80

Browse files
munyirikmjbvz
authored andcommitted
Provide ability to add project references (#1318)
* Provide ability to add project references This change updates NodejsProjectNode to detect if the UWP project flavor is active to provide support for project references. Alternative approach could have been to make NodejsProjectNode public (so that I could reference it from the UWP project system) but that would cause a huge changes as opposed to this less intrusive change. * Move GetProviderContexts to virtual method Also moves checks for adding/removing reference providers to virtual methods as well.
1 parent daffc33 commit 5f7ea80

File tree

4 files changed

+196
-60
lines changed

4 files changed

+196
-60
lines changed

Common/Product/SharedProject/ProjectNode.cs

Lines changed: 179 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ internal abstract partial class ProjectNode : HierarchyNode,
6363
IBuildDependencyUpdate,
6464
IVsProjectSpecialFiles,
6565
IVsProjectBuildSystem,
66-
IOleCommandTarget {
66+
IOleCommandTarget,
67+
IVsReferenceManagerUser {
6768
#region nested types
6869

6970
#if DEV14_OR_LATER
@@ -1383,71 +1384,191 @@ public virtual VSADDRESULT RunWizard(HierarchyNode parentNode, string itemName,
13831384
}
13841385

13851386
/// <summary>
1386-
/// This overrides the base class method to show the VS 2005 style Add reference dialog. The ProjectNode implementation
1387-
/// shows the VS 2003 style Add Reference dialog.
1387+
/// Shows the Add Reference dialog.
13881388
/// </summary>
1389-
/// <returns>S_OK if succeeded. Failure other wise</returns>
1390-
public virtual int AddProjectReference() {
1391-
IVsComponentSelectorDlg2 componentDialog;
1392-
Guid guidEmpty = Guid.Empty;
1393-
VSCOMPONENTSELECTORTABINIT[] tabInit = new VSCOMPONENTSELECTORTABINIT[4];
1394-
string strBrowseLocations = Path.GetDirectoryName(ProjectHome);
1389+
/// <returns>S_OK if succeeded. Failure otherwise</returns>
1390+
public int AddProjectReference() {
1391+
var referenceManager = this.GetService(typeof(SVsReferenceManager)) as IVsReferenceManager;
1392+
if (referenceManager != null) {
1393+
var contextGuids = new[] {
1394+
VSConstants.ProjectReferenceProvider_Guid,
1395+
VSConstants.FileReferenceProvider_Guid
1396+
};
1397+
referenceManager.ShowReferenceManager(
1398+
this,
1399+
SR.GetString(SR.AddReferenceDialogTitle),
1400+
"VS.ReferenceManager",
1401+
contextGuids.First(),
1402+
false);
1403+
return VSConstants.S_OK;
1404+
} else {
1405+
return VSConstants.E_NOINTERFACE;
1406+
}
1407+
}
13951408

1396-
//Add the Project page
1397-
tabInit[0].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
1398-
// Tell the Add Reference dialog to call hierarchies GetProperty with the following
1399-
// propID to enable filtering out ourself from the Project to Project reference
1400-
tabInit[0].varTabInitInfo = (int)__VSHPROPID.VSHPROPID_ShowProjInSolutionPage;
1401-
tabInit[0].guidTab = VSConstants.GUID_SolutionPage;
1409+
#region IVsReferenceManagerUser Members
14021410

1403-
// Add the Browse for file page
1404-
tabInit[1].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
1405-
tabInit[1].guidTab = VSConstants.GUID_COMPlusPage;
1406-
tabInit[1].varTabInitInfo = 0;
1411+
void IVsReferenceManagerUser.ChangeReferences(uint operation, IVsReferenceProviderContext changedContext) {
1412+
var op = (__VSREFERENCECHANGEOPERATION)operation;
1413+
__VSREFERENCECHANGEOPERATIONRESULT result;
14071414

1408-
// Add the Browse for file page
1409-
tabInit[2].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
1410-
tabInit[2].guidTab = VSConstants.GUID_BrowseFilePage;
1411-
tabInit[2].varTabInitInfo = 0;
1415+
try {
1416+
if (op == __VSREFERENCECHANGEOPERATION.VSREFERENCECHANGEOPERATION_ADD) {
1417+
result = this.AddReferences(changedContext);
1418+
} else {
1419+
result = this.RemoveReferences(changedContext);
1420+
}
1421+
} catch (InvalidOperationException e) {
1422+
Debug.Fail(e.ToString());
1423+
result = __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_DENY;
1424+
}
14121425

1413-
// Add the WebPI page
1414-
tabInit[3].dwSize = (uint)Marshal.SizeOf(typeof(VSCOMPONENTSELECTORTABINIT));
1415-
tabInit[3].guidTab = typeof(WebPiComponentPickerControl).GUID;
1416-
tabInit[3].varTabInitInfo = 0;
1426+
if (result == __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_DENY) {
1427+
throw new InvalidOperationException();
1428+
}
1429+
}
14171430

1418-
uint pX = 0, pY = 0;
1431+
Array IVsReferenceManagerUser.GetProviderContexts() {
1432+
return this.GetProviderContexts();
1433+
}
14191434

1420-
componentDialog = GetService(typeof(SVsComponentSelectorDlg)) as IVsComponentSelectorDlg2;
1421-
try {
1422-
// call the container to open the add reference dialog.
1423-
if (componentDialog != null) {
1424-
// Let the project know not to show itself in the Add Project Reference Dialog page
1425-
ShowProjectInSolutionPage = false;
1426-
1427-
// call the container to open the add reference dialog.
1428-
ErrorHandler.ThrowOnFailure(componentDialog.ComponentSelectorDlg2(
1429-
(System.UInt32)(__VSCOMPSELFLAGS.VSCOMSEL_MultiSelectMode | __VSCOMPSELFLAGS.VSCOMSEL_IgnoreMachineName),
1430-
(IVsComponentUser)this,
1431-
0,
1432-
null,
1433-
SR.GetString(SR.AddReferenceDialogTitle), // Title
1434-
"VS.AddReference", // Help topic
1435-
ref pX,
1436-
ref pY,
1437-
(uint)tabInit.Length,
1438-
tabInit,
1439-
ref guidEmpty,
1440-
AddReferenceExtensions.Replace('|', '\0') + "\0",
1441-
ref strBrowseLocations));
1442-
}
1443-
} catch (COMException e) {
1444-
Trace.WriteLine("Exception : " + e.Message);
1445-
return e.ErrorCode;
1446-
} finally {
1447-
// Let the project know it can show itself in the Add Project Reference Dialog page
1448-
ShowProjectInSolutionPage = true;
1435+
#endregion
1436+
1437+
protected virtual Array GetProviderContexts() {
1438+
var referenceManager = this.GetService(typeof(SVsReferenceManager)) as IVsReferenceManager;
1439+
1440+
var contextProviders = new[] {
1441+
CreateProjectReferenceProviderContext(referenceManager),
1442+
CreateFileReferenceProviderContext(referenceManager),
1443+
};
1444+
1445+
return contextProviders;
1446+
}
1447+
1448+
private IVsReferenceProviderContext CreateProjectReferenceProviderContext(IVsReferenceManager mgr) {
1449+
var context = mgr.CreateProviderContext(VSConstants.ProjectReferenceProvider_Guid) as IVsProjectReferenceProviderContext;
1450+
context.CurrentProject = this;
1451+
1452+
var referenceContainer = this.GetReferenceContainer();
1453+
var references = referenceContainer
1454+
.EnumReferences()
1455+
.OfType<ProjectReferenceNode>();
1456+
foreach (var reference in references) {
1457+
var newReference = context.CreateReference() as IVsProjectReference;
1458+
newReference.Identity = reference.ReferencedProjectGuid.ToString("B");
14491459
}
1450-
return VSConstants.S_OK;
1460+
1461+
return context as IVsReferenceProviderContext;
1462+
}
1463+
1464+
private IVsReferenceProviderContext CreateFileReferenceProviderContext(IVsReferenceManager mgr) {
1465+
var context = mgr.CreateProviderContext(VSConstants.FileReferenceProvider_Guid) as IVsFileReferenceProviderContext;
1466+
1467+
context.BrowseFilter = AddReferenceExtensions.Replace('|', '\0') + "\0";
1468+
return context as IVsReferenceProviderContext;
1469+
}
1470+
1471+
private __VSREFERENCECHANGEOPERATIONRESULT AddReferences(IVsReferenceProviderContext context) {
1472+
var addedReferences = this.GetAddedReferences(context);
1473+
1474+
var referenceContainer = this.GetReferenceContainer();
1475+
foreach (var selectorData in addedReferences) {
1476+
referenceContainer.AddReferenceFromSelectorData(selectorData);
1477+
}
1478+
1479+
return __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_ALLOW;
1480+
}
1481+
1482+
protected virtual IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsReferenceProviderContext context) {
1483+
var addedReferences = Enumerable.Empty<VSCOMPONENTSELECTORDATA>();
1484+
1485+
if (context.ProviderGuid == VSConstants.ProjectReferenceProvider_Guid) {
1486+
addedReferences = GetAddedReferences(context as IVsProjectReferenceProviderContext);
1487+
}
1488+
else if (context.ProviderGuid == VSConstants.FileReferenceProvider_Guid) {
1489+
addedReferences = GetAddedReferences(context as IVsFileReferenceProviderContext);
1490+
}
1491+
1492+
return addedReferences;
1493+
}
1494+
1495+
private __VSREFERENCECHANGEOPERATIONRESULT RemoveReferences(IVsReferenceProviderContext context) {
1496+
var removedReferences = this.GetRemovedReferences(context);
1497+
1498+
foreach (var refNode in removedReferences) {
1499+
refNode.Remove(true /* delete from storage*/);
1500+
}
1501+
1502+
return __VSREFERENCECHANGEOPERATIONRESULT.VSREFERENCECHANGEOPERATIONRESULT_ALLOW;
1503+
}
1504+
1505+
protected virtual IEnumerable<ReferenceNode> GetRemovedReferences(IVsReferenceProviderContext context) {
1506+
var removedReferences = Enumerable.Empty<ReferenceNode>();
1507+
1508+
if (context.ProviderGuid == VSConstants.ProjectReferenceProvider_Guid) {
1509+
removedReferences = GetRemovedReferences(context as IVsProjectReferenceProviderContext);
1510+
}
1511+
else if (context.ProviderGuid == VSConstants.FileReferenceProvider_Guid) {
1512+
removedReferences = GetRemovedReferences(context as IVsFileReferenceProviderContext);
1513+
}
1514+
1515+
return removedReferences;
1516+
}
1517+
1518+
private IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsProjectReferenceProviderContext context) {
1519+
var selectedReferences = context
1520+
.References
1521+
.OfType<IVsProjectReference>()
1522+
.Select(reference => new VSCOMPONENTSELECTORDATA() {
1523+
type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project,
1524+
bstrTitle = reference.Name,
1525+
bstrFile = new FileInfo(reference.FullPath).Directory.FullName,
1526+
bstrProjRef = reference.ReferenceSpecification,
1527+
});
1528+
1529+
return selectedReferences;
1530+
}
1531+
1532+
private IEnumerable<ReferenceNode> GetRemovedReferences(IVsProjectReferenceProviderContext context) {
1533+
var selectedReferences = context
1534+
.References
1535+
.OfType<IVsProjectReference>()
1536+
.Select(asmRef => new Guid(asmRef.Identity));
1537+
1538+
var referenceContainer = this.GetReferenceContainer();
1539+
var references = referenceContainer
1540+
.EnumReferences()
1541+
.OfType<ProjectReferenceNode>()
1542+
.Where(refNode => selectedReferences.Contains(refNode.ReferencedProjectGuid));
1543+
1544+
return references;
1545+
}
1546+
1547+
private IEnumerable<VSCOMPONENTSELECTORDATA> GetAddedReferences(IVsFileReferenceProviderContext context) {
1548+
var selectedReferences = context
1549+
.References
1550+
.OfType<IVsFileReference>()
1551+
.Select(reference => new VSCOMPONENTSELECTORDATA() {
1552+
type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_File,
1553+
bstrFile = reference.FullPath,
1554+
});
1555+
1556+
return selectedReferences;
1557+
}
1558+
1559+
private IEnumerable<ReferenceNode> GetRemovedReferences(IVsFileReferenceProviderContext context) {
1560+
var selectedReferences = context
1561+
.References
1562+
.OfType<IVsFileReference>()
1563+
.Select(fileRef => fileRef.FullPath);
1564+
1565+
var referenceContainer = this.GetReferenceContainer();
1566+
var references = referenceContainer
1567+
.EnumReferences()
1568+
.OfType<ReferenceNode>()
1569+
.Where(refNode => selectedReferences.Contains(refNode.Url));
1570+
1571+
return references;
14511572
}
14521573

14531574
protected virtual string AddReferenceExtensions {

Common/Product/SharedProject/ProjectResources.resx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ Run Visual Studio with the /Log option and check ActivityLog.xml for more detail
609609
{0}</value>
610610
</data>
611611
<data name="AddReferenceExtensions" xml:space="preserve">
612-
<value>Dynamic Link Libraries (*.dll)|*.dll|All Files (*.*)|*.*</value>
612+
<value>Component Files|*.winmd</value>
613613
</data>
614614
<data name="WebPiFeedError" xml:space="preserve">
615615
<value>Unable to get feed "{0}".

Nodejs/Product/Nodejs/Guids.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,8 @@ static class Guids {
7474

7575
public const string OfficeToolsBootstrapperCmdSetString = "{D26C976C-8EE8-4EC4-8746-F5F7702A17C5}";
7676
public static readonly Guid OfficeToolsBootstrapperCmdSet = new Guid(OfficeToolsBootstrapperCmdSetString);
77+
78+
// UWP project flavor guid
79+
public const string NodejsUwpProjectFlavor = "00251F00-BA30-4CE4-96A2-B8A1085F37AA";
7780
};
7881
}

Nodejs/Product/Nodejs/Project/NodejsProjectNode.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,19 @@ internal override object Object {
614614
}
615615

616616
protected override ReferenceContainerNode CreateReferenceContainerNode() {
617-
return null;
617+
// Only create a reference node if the project is targeting UWP
618+
if(GetProjectTypeGuids().Contains(Guids.NodejsUwpProjectFlavor)) {
619+
return base.CreateReferenceContainerNode();
620+
} else {
621+
return null;
622+
}
623+
}
624+
625+
private string GetProjectTypeGuids()
626+
{
627+
string projectTypeGuids = "";
628+
ErrorHandler.ThrowOnFailure(((IVsAggregatableProject)this).GetAggregateProjectTypeGuids(out projectTypeGuids));
629+
return projectTypeGuids;
618630
}
619631

620632
public NodeModulesNode ModulesNode { get; private set; }

0 commit comments

Comments
 (0)