Skip to content

Commit

Permalink
Merge pull request #19872 from tmeschter/HandleWebApplicationProjects
Browse files Browse the repository at this point in the history
Exclude projects for aspx/cshtml/vbhtml files
  • Loading branch information
tmeschter committed May 31, 2017
2 parents 8d1d7ae + d6ebdee commit 237f04c
Showing 1 changed file with 55 additions and 40 deletions.
Expand Up @@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Implementation.Venus;
using Microsoft.VisualStudio.Shell;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.SolutionExplorer
Expand Down Expand Up @@ -43,56 +44,70 @@ public bool TryGetProjectId(IVsHierarchyItem hierarchyItem, string targetFramewo
return false;
}

var project = _workspace.DeferredState.ProjectTracker.ImmutableProjects
.Where(p =>
// First filter the projects by matching up properties on the input hierarchy against properties on each
// project's hierarchy.
var candidateProjects = _workspace.DeferredState.ProjectTracker.ImmutableProjects
.Where(p =>
{
// We're about to access various properties of the IVsHierarchy associated with the project.
// The properties supported and the interpretation of their values varies from one project system
// to another. This code is designed with C# and VB in mind, so we need to filter out everything
// else.
if (p.Language != LanguageNames.CSharp
&& p.Language != LanguageNames.VisualBasic)
{
// We're about to access various properties of the IVsHierarchy associated with the project.
// The properties supported and the interpretation of their values varies from one project system
// to another. This code is designed with C# and VB in mind, so we need to filter out everything
// else.
if (p.Language != LanguageNames.CSharp
&& p.Language != LanguageNames.VisualBasic)
{
return false;
}
return false;
}
// Here we try to match the hierarchy from Solution Explorer to a hierarchy from the Roslyn project.
// The canonical name of a hierarchy item must be unique _within_ an hierarchy, but since we're
// examining multiple hierarchies the canonical name could be the same. Indeed this happens when two
// project files are in the same folder--they both use the full path to the _folder_ as the canonical
// name. To distinguish them we also examine the "regular" name, which will necessarily be different
// if the two projects are in the same folder.
// Note that if a project has been loaded with Lightweight Solution Load it won't even have a
// hierarchy, so we need to check for null first.
if (p.Hierarchy != null
&& p.Hierarchy.TryGetCanonicalName((uint)VSConstants.VSITEMID.Root, out string projectCanonicalName)
&& p.Hierarchy.TryGetItemName((uint)VSConstants.VSITEMID.Root, out string projectName)
&& projectCanonicalName.Equals(nestedCanonicalName, System.StringComparison.OrdinalIgnoreCase)
&& projectName.Equals(nestedName))
// Here we try to match the hierarchy from Solution Explorer to a hierarchy from the Roslyn project.
// The canonical name of a hierarchy item must be unique _within_ an hierarchy, but since we're
// examining multiple hierarchies the canonical name could be the same. Indeed this happens when two
// project files are in the same folder--they both use the full path to the _folder_ as the canonical
// name. To distinguish them we also examine the "regular" name, which will necessarily be different
// if the two projects are in the same folder.
// Note that if a project has been loaded with Lightweight Solution Load it won't even have a
// hierarchy, so we need to check for null first.
if (p.Hierarchy != null
&& p.Hierarchy.TryGetCanonicalName((uint)VSConstants.VSITEMID.Root, out string projectCanonicalName)
&& p.Hierarchy.TryGetItemName((uint)VSConstants.VSITEMID.Root, out string projectName)
&& projectCanonicalName.Equals(nestedCanonicalName, System.StringComparison.OrdinalIgnoreCase)
&& projectName.Equals(nestedName))
{
if (targetFrameworkMoniker == null)
{
if (targetFrameworkMoniker == null)
{
return true;
}
return p.Hierarchy.TryGetTargetFrameworkMoniker((uint)VSConstants.VSITEMID.Root, out string projectTargetFrameworkMoniker)
&& projectTargetFrameworkMoniker.Equals(targetFrameworkMoniker);
return true;
}
return false;
})
.SingleOrDefault();
return p.Hierarchy.TryGetTargetFrameworkMoniker((uint)VSConstants.VSITEMID.Root, out string projectTargetFrameworkMoniker)
&& projectTargetFrameworkMoniker.Equals(targetFrameworkMoniker);
}
return false;
})
.ToArray();

if (project == null)
// If we only have one candidate then no further checks are required.
if (candidateProjects.Length == 1)
{
projectId = default(ProjectId);
return false;
projectId = candidateProjects[0].Id;
return true;
}
else

// If we have multiple candidates then we might be dealing with Web Application Projects. In this case
// there will be one main project plus one project for each open aspx/cshtml/vbhtml file, all with
// identical properties on their hierarchies. We can find the main project by taking the first project
// without a ContainedDocument.
foreach (var candidateProject in candidateProjects)
{
projectId = project.Id;
return true;
if (!candidateProject.GetCurrentDocuments().Any(doc => doc is ContainedDocument))
{
projectId = candidateProject.Id;
return true;
}
}

projectId = default(ProjectId);
return false;
}
}
}

0 comments on commit 237f04c

Please sign in to comment.