public DocumentId FindProjectDocumentIdWithItemId(uint itemidInsertionPoint) { var hierarchy = _workspace.GetHierarchy(_project.Id); foreach (var document in _workspace.CurrentSolution.GetProject(_project.Id).Documents) { if (document.FilePath != null && hierarchy.TryGetItemId(document.FilePath) == itemidInsertionPoint) { return(document.Id); } } return(null); }
private static bool ProjectIdMatchesHierarchy(VisualStudioWorkspace workspace, ProjectId projectId, IVsHierarchy hierarchy) { var hierarchyForProject = workspace.GetHierarchy(projectId); if (hierarchyForProject == null) { return(false); } if (hierarchyForProject == hierarchy) { return(true); } // For CPS, the hierarchy for the Roslyn project isn't the same as the one // we get from Solution Explorer (it's a wrapper implementation), so we'll // have to compare properties. hierarchyForProject.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_Name, out var rawValue); if (rawValue is string projectName) { hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_Name, out rawValue); return(projectName == (rawValue as string)); } return(false); }
private Assembly ResolveAssembly(ProjectId projectId, string assemblyName) { this.AssertIsForeground(); if (_workspace == null) { return(null); } var hierarchy = _workspace.GetHierarchy(projectId); if (hierarchy == null || !hierarchy.TryGetProperty((__VSHPROPID)__VSHPROPID4.VSHPROPID_TargetFrameworkMoniker, out string targetMoniker) || targetMoniker == null) { return(null); } try { // Below we use the DesignTimeAssemblyResolver functionality of VS to // determine if we can resolve the specified assembly name in the context // of this project. However, this service does not do the right thing // in UWP apps. Specifically, it *will* resolve the assembly to a // reference assembly, even though that's never what we want. In order // to deal with that, we put in this little check where we do not allow // reference assembly resolution if the projects TargetFrameworkMoniker // is ".NETCore, Version=5.0" or greater. var frameworkName = new FrameworkName(targetMoniker); if (StringComparer.OrdinalIgnoreCase.Equals(frameworkName.Identifier, ".NETCore") && frameworkName.Version >= new Version(major: 5, minor: 0)) { return(null); } } catch (ArgumentException) { // Something wrong with our TFM. We don't have enough information to // properly resolve this assembly name. return(null); } try { var frameworkProvider = new VsTargetFrameworkProvider( (IVsFrameworkMultiTargeting)_serviceProvider.GetService(typeof(SVsFrameworkMultiTargeting)), targetMoniker, (IVsSmartOpenScope)_serviceProvider.GetService(typeof(SVsSmartOpenScope))); return(frameworkProvider.GetReflectionAssembly(new AssemblyName(assemblyName))); } catch (InvalidOperationException) { // VsTargetFrameworkProvider throws InvalidOperationException in the // some cases (like when targeting packs are missing). In that case // we can't resolve this path. return(null); } }
public IReadOnlyDictionary <string, IEnumerable <DiagnosticDescriptor> > GetAllDiagnosticDescriptors(IVsHierarchy?hierarchy) { var currentSolution = _workspace.CurrentSolution; var infoCache = _diagnosticService.AnalyzerInfoCache; var hostAnalyzers = currentSolution.State.Analyzers; if (hierarchy == null) { return(Transform(hostAnalyzers.GetDiagnosticDescriptorsPerReference(infoCache))); } // Analyzers are only supported for C# and VB currently. var projectsWithHierarchy = currentSolution.Projects .Where(p => p.Language is LanguageNames.CSharp or LanguageNames.VisualBasic) .Where(p => _workspace.GetHierarchy(p.Id) == hierarchy); if (projectsWithHierarchy.Count() <= 1) { var project = projectsWithHierarchy.FirstOrDefault(); if (project == null) { return(Transform(hostAnalyzers.GetDiagnosticDescriptorsPerReference(infoCache))); } else { return(Transform(hostAnalyzers.GetDiagnosticDescriptorsPerReference(infoCache, project))); } } else { // Multiple workspace projects map to the same hierarchy, return a union of descriptors for all projects. // For example, this can happen for web projects where we create on the fly projects for aspx files. var descriptorsMap = ImmutableDictionary.CreateBuilder <string, IEnumerable <DiagnosticDescriptor> >(); foreach (var project in projectsWithHierarchy) { var descriptorsPerReference = hostAnalyzers.GetDiagnosticDescriptorsPerReference(infoCache, project); foreach (var(displayName, descriptors) in descriptorsPerReference) { if (descriptorsMap.TryGetValue(displayName, out var existingDescriptors)) { descriptorsMap[displayName] = existingDescriptors.Concat(descriptors).Distinct(); } else { descriptorsMap[displayName] = descriptors; } } } return(descriptorsMap.ToImmutable()); } }
private Dictionary <IVsHierarchy, List <uint> > GetHierarchiesAndItemIDsFromDocumentIDs( VisualStudioWorkspace visualStudioWorkspace, IEnumerable <DocumentId> changedDocumentIDs ) { AssertIsForeground(); var hierarchyToItemIDsMap = new Dictionary <IVsHierarchy, List <uint> >(); foreach (var documentId in changedDocumentIDs) { var hierarchy = visualStudioWorkspace.GetHierarchy(documentId.ProjectId); if (hierarchy == null) { continue; } var document = visualStudioWorkspace.CurrentSolution.GetDocument(documentId); var itemID = hierarchy.TryGetItemId(document.FilePath); if (itemID == VSConstants.VSITEMID_NIL) { continue; } if ( !hierarchyToItemIDsMap.TryGetValue( hierarchy, out var itemIDsForCurrentHierarchy ) ) { itemIDsForCurrentHierarchy = new List <uint>(); hierarchyToItemIDsMap.Add(hierarchy, itemIDsForCurrentHierarchy); } if (!itemIDsForCurrentHierarchy.Contains(itemID)) { itemIDsForCurrentHierarchy.Add(itemID); } } return(hierarchyToItemIDsMap); }
// *DO NOT DELETE* // This is used by Ruleset Editor from ManagedSourceCodeAnalysis.dll. public IReadOnlyDictionary <string, IEnumerable <DiagnosticDescriptor> > GetAllDiagnosticDescriptors(IVsHierarchy hierarchyOpt) { if (hierarchyOpt == null) { return(Transform(_diagnosticService.CreateDiagnosticDescriptorsPerReference(projectOpt: null))); } // Analyzers are only supported for C# and VB currently. var projectsWithHierarchy = _workspace.CurrentSolution.Projects .Where(p => p.Language == LanguageNames.CSharp || p.Language == LanguageNames.VisualBasic) .Where(p => _workspace.GetHierarchy(p.Id) == hierarchyOpt); if (projectsWithHierarchy.Count() <= 1) { return(Transform(_diagnosticService.CreateDiagnosticDescriptorsPerReference(projectsWithHierarchy.FirstOrDefault()))); } else { // Multiple workspace projects map to the same hierarchy, return a union of descriptors for all projects. // For example, this can happen for web projects where we create on the fly projects for aspx files. var descriptorsMap = ImmutableDictionary.CreateBuilder <string, IEnumerable <DiagnosticDescriptor> >(); foreach (var project in projectsWithHierarchy) { var newDescriptorTuples = _diagnosticService.CreateDiagnosticDescriptorsPerReference(project); foreach (var kvp in newDescriptorTuples) { if (descriptorsMap.TryGetValue(kvp.Key, out var existingDescriptors)) { descriptorsMap[kvp.Key] = existingDescriptors.Concat(kvp.Value).Distinct(); } else { descriptorsMap[kvp.Key] = kvp.Value; } } } return(descriptorsMap.ToImmutable()); } }
public AbstractLegacyProject( string projectSystemName, IVsHierarchy hierarchy, string language, bool isVsIntellisenseProject, IServiceProvider serviceProvider, IThreadingContext threadingContext, string externalErrorReportingPrefix ) : base(threadingContext, assertIsForeground: true) { Contract.ThrowIfNull(hierarchy); var componentModel = (IComponentModel)serviceProvider.GetService( typeof(SComponentModel) ); Workspace = componentModel.GetService <VisualStudioWorkspace>(); var workspaceImpl = (VisualStudioWorkspaceImpl)Workspace; var projectFilePath = hierarchy.TryGetProjectFilePath(); if (projectFilePath != null && !File.Exists(projectFilePath)) { projectFilePath = null; } if (projectFilePath != null) { _projectDirectory = Path.GetDirectoryName(projectFilePath); } if (isVsIntellisenseProject) { // IVsIntellisenseProjects are usually used for contained language cases, which means these projects don't have any real // output path that we should consider. Since those point to the same IVsHierarchy as another project, we end up with two projects // with the same output path, which potentially breaks conversion of metadata references to project references. However they're // also used for database projects and a few other cases where there there isn't a "primary" IVsHierarchy. // As a heuristic here we'll ignore the output path if we already have another project tied to the IVsHierarchy. foreach (var projectId in Workspace.CurrentSolution.ProjectIds) { if (Workspace.GetHierarchy(projectId) == hierarchy) { _ignoreOutputPath = true; break; } } } var projectFactory = componentModel.GetService <VisualStudioProjectFactory>(); VisualStudioProject = threadingContext.JoinableTaskFactory.Run( () => projectFactory.CreateAndAddToWorkspaceAsync( projectSystemName, language, new VisualStudioProjectCreationInfo { // The workspace requires an assembly name so we can make compilations. We'll use // projectSystemName because they'll have a better one eventually. AssemblyName = projectSystemName, FilePath = projectFilePath, Hierarchy = hierarchy, ProjectGuid = GetProjectIDGuid(hierarchy), }, CancellationToken.None ) ); workspaceImpl.AddProjectRuleSetFileToInternalMaps( VisualStudioProject, () => VisualStudioProjectOptionsProcessor.EffectiveRuleSetFilePath ); // Right now VB doesn't have the concept of "default namespace". But we conjure one in workspace // by assigning the value of the project's root namespace to it. So various feature can choose to // use it for their own purpose. // In the future, we might consider officially exposing "default namespace" for VB project // (e.g. through a <defaultnamespace> msbuild property) VisualStudioProject.DefaultNamespace = GetRootNamespacePropertyValue(hierarchy); if ( TryGetPropertyValue( hierarchy, AdditionalPropertyNames.MaxSupportedLangVersion, out var maxLangVer ) ) { VisualStudioProject.MaxLangVersion = maxLangVer; } if ( TryGetBoolPropertyValue( hierarchy, AdditionalPropertyNames.RunAnalyzers, out var runAnayzers ) ) { VisualStudioProject.RunAnalyzers = runAnayzers; } if ( TryGetBoolPropertyValue( hierarchy, AdditionalPropertyNames.RunAnalyzersDuringLiveAnalysis, out var runAnayzersDuringLiveAnalysis ) ) { VisualStudioProject.RunAnalyzersDuringLiveAnalysis = runAnayzersDuringLiveAnalysis; } Hierarchy = hierarchy; ConnectHierarchyEvents(); RefreshBinOutputPath(); workspaceImpl.SubscribeExternalErrorDiagnosticUpdateSourceToSolutionBuildEvents(); _externalErrorReporter = new ProjectExternalErrorReporter( VisualStudioProject.Id, externalErrorReportingPrefix, language, workspaceImpl ); _batchScopeCreator = componentModel.GetService <SolutionEventsBatchScopeCreator>(); _batchScopeCreator.StartTrackingProject(VisualStudioProject, Hierarchy); }
internal Project GetProjectFromHierarchy(IVsHierarchy hierarchy) => _workspace.CurrentSolution.Projects.FirstOrDefault(proj => _workspace.GetHierarchy(proj.Id) == hierarchy);
public static Project GetProject(IVsHierarchy projectHierarchy, VisualStudioWorkspace visualStudioWorkspace) { return(visualStudioWorkspace.CurrentSolution.Projects .FirstOrDefault(p => projectHierarchy == visualStudioWorkspace.GetHierarchy(p.Id))); }
public bool TryGetProjectId(IVsHierarchyItem hierarchyItem, string targetFrameworkMoniker, out ProjectId projectId) { // A project node is represented in two different hierarchies: the solution's IVsHierarchy (where it is a leaf node) // and the project's own IVsHierarchy (where it is the root node). The IVsHierarchyItem joins them together for the // purpose of creating the tree displayed in Solution Explorer. The project's hierarchy is what is passed from the // project system to the language service, so that's the one the one to query here. To do that we need to get // the "nested" hierarchy from the IVsHierarchyItem. var nestedHierarchy = hierarchyItem.HierarchyIdentity.NestedHierarchy; var nestedHierarchyId = hierarchyItem.HierarchyIdentity.NestedItemID; if (!nestedHierarchy.TryGetCanonicalName(nestedHierarchyId, out string nestedCanonicalName) || !nestedHierarchy.TryGetItemName(nestedHierarchyId, out string nestedName)) { projectId = default(ProjectId); return(false); } // First filter the projects by matching up properties on the input hierarchy against properties on each // project's hierarchy. var candidateProjects = _workspace.CurrentSolution.Projects .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) { 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. var hierarchy = _workspace.GetHierarchy(p.Id); if (hierarchy != null && hierarchy.TryGetCanonicalName((uint)VSConstants.VSITEMID.Root, out string projectCanonicalName) && hierarchy.TryGetItemName((uint)VSConstants.VSITEMID.Root, out string projectName) && projectCanonicalName.Equals(nestedCanonicalName, System.StringComparison.OrdinalIgnoreCase) && projectName.Equals(nestedName)) { if (targetFrameworkMoniker == null) { return(true); } return(hierarchy.TryGetTargetFrameworkMoniker((uint)VSConstants.VSITEMID.Root, out string projectTargetFrameworkMoniker) && projectTargetFrameworkMoniker.Equals(targetFrameworkMoniker)); } return(false); }) .ToArray(); // If we only have one candidate then no further checks are required. if (candidateProjects.Length == 1) { projectId = candidateProjects[0].Id; return(true); } // 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) { if (!candidateProject.DocumentIds.Any(id => ContainedDocument.TryGetContainedDocument(id) != null)) { projectId = candidateProject.Id; return(true); } } projectId = default(ProjectId); return(false); }