protected override void Initialize() { ThreadHelper.ThrowIfNotOnUIThread(); base.Initialize(); // Now retrieve all needed services _enumHierarchyItemsFactory = Package.GetGlobalService(typeof(SVsEnumHierarchyItemsFactory)) as IVsEnumHierarchyItemsFactory; _solutionService = Package.GetGlobalService(typeof(SVsSolution)) as IVsSolution; }
private static List <string> GetExcludedReferences( EnvDTEProject project, IVsEnumHierarchyItemsFactory itemsFactory) { var excludedReferences = new List <string>(); var hierarchy = VsHierarchyUtility.ToVsHierarchy(project); // Get all items in the hierarchy, this includes project references, files, and everything else. IEnumHierarchyItems items; if (ErrorHandler.Succeeded(itemsFactory.EnumHierarchyItems( hierarchy, (uint)__VSEHI.VSEHI_Leaf, (uint)VSConstants.VSITEMID.Root, out items))) { var buildPropertyStorage = (IVsBuildPropertyStorage)hierarchy; // Loop through all items uint fetched; VSITEMSELECTION[] item = new VSITEMSELECTION[1]; while (ErrorHandler.Succeeded(items.Next(1, item, out fetched)) && fetched == 1) { // Check if the item has ReferenceOutputAssembly. This will // return null for the vast majority of items. string value; if (ErrorHandler.Succeeded(buildPropertyStorage.GetItemAttribute( item[0].itemid, "ReferenceOutputAssembly", out value)) && value != null) { // We only need to go farther if the flag exists and is not true if (!string.Equals(value, bool.TrueString, StringComparison.OrdinalIgnoreCase)) { // Get the DTE Project reference for the item id. This checks for nulls incase this is // somehow not a project reference that had the ReferenceOutputAssembly flag. object childObject; if (ErrorHandler.Succeeded(hierarchy.GetProperty( item[0].itemid, (int)__VSHPROPID.VSHPROPID_ExtObject, out childObject))) { // 1. Verify that this is a project reference // 2. Check that it is valid and resolved // 3. Follow the reference to the DTE project and get the unique name var reference = childObject as Reference3; if (reference != null && reference.Resolved && reference.SourceProject != null) { var childPath = EnvDTEProjectInfoUtility .GetFullProjectPath(reference.SourceProject); excludedReferences.Add(childPath); } } } } } } return(excludedReferences); }
/// <summary> /// Get only the direct dependencies from a project /// </summary> private DirectReferences GetDirectProjectReferences( EnvDTEProject project, string projectFileFullPath, ExternalProjectReferenceContext context, IVsEnumHierarchyItemsFactory itemsFactory, string rootProjectPath) { var logger = context.Logger; var cache = context.Cache; var result = new DirectReferences(); // Find a project.json in the project // This checks for files on disk to match how BuildIntegratedProjectSystem checks at creation time. // NuGet.exe also uses disk paths and not the project file. var projectName = Path.GetFileNameWithoutExtension(projectFileFullPath); var projectDirectory = Path.GetDirectoryName(projectFileFullPath); // Check for projectName.project.json and project.json string jsonConfigItem = ProjectJsonPathUtilities.GetProjectConfigPath( directoryPath: projectDirectory, projectName: projectName); var hasProjectJson = true; // Verify the file exists, otherwise clear it if (!File.Exists(jsonConfigItem)) { jsonConfigItem = null; hasProjectJson = false; } // Verify ReferenceOutputAssembly var excludedProjects = GetExcludedReferences(project, itemsFactory); var childReferences = new HashSet <string>(StringComparer.Ordinal); var hasMissingReferences = false; // find all references in the project foreach (var childReference in GetProjectReferences(project)) { try { var reference3 = childReference as Reference3; if (reference3 != null && !reference3.Resolved) { // Skip missing references and show a warning hasMissingReferences = true; continue; } // Skip missing references if (childReference.SourceProject != null) { if (EnvDTEProjectUtility.HasUnsupportedProjectCapability(childReference.SourceProject)) { // Skip this shared project continue; } var childName = EnvDTEProjectUtility.GetFullProjectPath(childReference.SourceProject); // Skip projects which have ReferenceOutputAssembly=false if (!string.IsNullOrEmpty(childName) && !excludedProjects.Contains(childName, StringComparer.OrdinalIgnoreCase)) { childReferences.Add(childName); result.ToProcess.Add(new DTEReference(childReference.SourceProject, childName)); } } else if (hasProjectJson) { // SDK references do not have a SourceProject or child references, // but they can contain project.json files, and should be part of the closure // SDKs are not projects, only the project.json name is checked here var possibleSdkPath = childReference.Path; if (!string.IsNullOrEmpty(possibleSdkPath) && !possibleSdkPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && Directory.Exists(possibleSdkPath)) { var possibleProjectJson = Path.Combine( possibleSdkPath, ProjectJsonPathUtilities.ProjectConfigFileName); if (File.Exists(possibleProjectJson)) { childReferences.Add(possibleProjectJson); // add the sdk to the results here result.Processed.Add(new ExternalProjectReference( possibleProjectJson, childReference.Name, possibleProjectJson, msbuildProjectPath: null, projectReferences: Enumerable.Empty <string>())); } } } } catch (Exception ex) { // Exceptions are expected in some scenarios for native projects, // ignore them and show a warning hasMissingReferences = true; logger.LogDebug(ex.ToString()); Debug.Fail("Unable to find project closure: " + ex.ToString()); } } if (hasMissingReferences) { // Log a warning message once per project // This warning contains only the names of the root project and the project with the // broken reference. Attempting to display more details on the actual reference // that has the problem may lead to another exception being thrown. var warning = string.Format( CultureInfo.CurrentCulture, Strings.Warning_ErrorDuringProjectClosureWalk, projectName, rootProjectPath); logger.LogWarning(warning); } // For the xproj -> xproj -> csproj scenario find all xproj-> xproj references. if (projectFileFullPath.EndsWith(XProjUtility.XProjExtension, StringComparison.OrdinalIgnoreCase)) { // All xproj paths, these are already checked for project.json var xprojFiles = XProjUtility.GetProjectReferences(projectFileFullPath); if (xprojFiles.Count > 0) { var pathToProject = GetPathToDTEProjectLookup(project); foreach (var xProjPath in xprojFiles) { // Only add projects that we can find in the solution, otherwise they will // end up causing failures. If this is an actual failure the resolver will // fail when resolving the dependency from project.json Project xProjDTE; if (pathToProject.TryGetValue(xProjPath, out xProjDTE)) { var xProjFullPath = EnvDTEProjectUtility.GetFullProjectPath(xProjDTE); if (!string.IsNullOrEmpty(xProjFullPath)) { childReferences.Add(xProjFullPath); // Continue walking this project if it has not been walked already result.ToProcess.Add(new DTEReference(xProjDTE, xProjFullPath)); } } } } } // Only set a package spec project name if a package spec exists var packageSpecProjectName = jsonConfigItem == null ? null : projectName; // Add the parent project to the results result.Processed.Add(new ExternalProjectReference( projectFileFullPath, packageSpecProjectName, jsonConfigItem, projectFileFullPath, childReferences)); return(result); }