/// <summary> /// Get only the direct dependencies from a project /// </summary> private DirectReferences GetDirectProjectReferences( DotNetProject project, string projectFileFullPath, ExternalProjectReferenceContext context, 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); var childReferences = new HashSet <string> (StringComparer.Ordinal); var hasMissingReferences = false; // find all references in the project foreach (var childReference in project.References) { try { if (!childReference.IsValid) { // Skip missing references and show a warning hasMissingReferences = true; continue; } // Skip missing references DotNetProject sourceProject = null; if (childReference.ReferenceType == ReferenceType.Project) { sourceProject = childReference.ResolveProject(project.ParentSolution) as DotNetProject; } if (sourceProject != null) { string childName = sourceProject.FileName; // Skip projects which have ReferenceOutputAssembly=false if (!string.IsNullOrEmpty(childName) && !excludedProjects.Contains(childName, StringComparer.OrdinalIgnoreCase)) { childReferences.Add(childName); result.ToProcess.Add(new DotNetProjectReference(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.Message); LoggingService.LogError("Unable to find project closure.", ex); } } 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 = GettextCatalog.GetString("Failed to resolve all project references for '{0}'. The package restore result for '{1}' may be incomplete.", projectName, rootProjectPath); logger.LogWarning(warning); } // 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); }
/// <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); }