public static ProjectLoader Create(ILogger logger, string sourceRootFolder) { ProjectLoader projectLoader; if (!projectLoaderCache.TryGetValue(sourceRootFolder, out projectLoader)) { projectLoader = new ProjectLoader(logger); projectLoaderCache.Add(sourceRootFolder, projectLoader); } return projectLoader; }
public List<string> GetTargetProjectFiles(ProjectLoader projectLoader, string[] targetProjects) { var targetProjectFiles = new List<string>(); foreach (var assemblyName in targetProjects) { var projectFile = projectLoader.GetProjectByAssemblyName(assemblyName); if (projectFile == null) throw new Exception($"Project by assembly name {assemblyName} not found"); targetProjectFiles.Add(projectFile.ProjectFileLocation); } return targetProjectFiles; }
public GeneratedSolution CreateSolution(ProjectSetup projectSetup, ProjectLoader projectLoader, IEnumerable<string> projectLocations, string solutionFileLocation, string[] thirdPartyFolders, HashSet<string> usedThirdParties, string customAppend) { var solutionProjectList = ReferenceWalker.WalkReferencesRecursively(projectSetup, projectLoader, projectLocations, thirdPartyFolders, usedThirdParties); var solutionFile = new StringBuilder(); solutionFile.AppendLine(); solutionFile.AppendLine("Microsoft Visual Studio Solution File, Format Version 12.00"); solutionFile.AppendLine("# Visual Studio 14"); solutionFile.AppendLine("VisualStudioVersion = 14.0.24720.0"); solutionFile.AppendLine("MinimumVisualStudioVersion = 10.0.40219.1"); if (!string.IsNullOrWhiteSpace(customAppend)) { solutionFile.AppendLine(customAppend); } var testProjects = new List<Guid>(); var startProjects = new List<Guid>(); var otherProjects = new List<Guid>(); foreach (var projectId in solutionProjectList) { var project = projectLoader.GetProjectById(projectId); var isTestProject = project.AssemblyName.ToLowerInvariant().Contains("test"); var isStartProject = project.IsLauncher; if (isTestProject) testProjects.Add(projectId); else if (isStartProject) startProjects.Add(projectId); else otherProjects.Add(projectId); // FullProjectPath can be changed to relative, but then root folder is needed var projectFileLocation = MakeRelativePath(solutionFileLocation, project.ProjectFileLocation); solutionFile.AppendFormat("Project(\"{0}\") = \"{1}\", \"{2}\", \"{3}\"", "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", Path.GetFileNameWithoutExtension(projectFileLocation), projectFileLocation, project.ProjectId.ToString("B").ToUpperInvariant()); solutionFile.AppendLine(); #region DEPENDENCIES var dependencies = ReferenceWalker.GetProjectDependencies(projectSetup, projectLoader, project, thirdPartyFolders, usedThirdParties); if (dependencies != null && dependencies.Count > 0) { var projectSectionAdded = false; foreach (var dependentItemId in dependencies) { // do not add dependency to itself if (dependentItemId == project.ProjectId) continue; if (!projectSectionAdded) { solutionFile.AppendLine("\tProjectSection(ProjectDependencies) = postProject"); projectSectionAdded = true; } solutionFile.AppendFormat("\t\t{0} = {0}", dependentItemId.ToString("B").ToUpperInvariant()); solutionFile.AppendLine(); } if (projectSectionAdded) solutionFile.AppendLine("\tEndProjectSection"); } #endregion solutionFile.AppendLine("EndProject"); } var otherProjectId = Guid.NewGuid(); var testProjectId = Guid.NewGuid(); if (startProjects.Count > 0) { solutionFile.AppendLine($"Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"Projects\", \"Projects\", \"{otherProjectId.ToString("B").ToUpperInvariant()}\""); solutionFile.AppendLine("EndProject"); } if (testProjects.Count > 0) { solutionFile.AppendLine($"Project(\"{{2150E333-8FDC-42A3-9474-1A3956D46DE8}}\") = \"Tests\", \"Tests\", \"{testProjectId.ToString("B").ToUpperInvariant()}\""); solutionFile.AppendLine("EndProject"); } solutionFile.AppendLine("Global"); #region GLOBAL SECTION solutionFile.AppendLine("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"); solutionFile.AppendLine("\t\tDebug|Any CPU = Debug|Any CPU"); solutionFile.AppendLine("\t\tDebug|Mixed Platforms = Debug|Mixed Platforms"); solutionFile.AppendLine("\t\tDebug|X64 = Debug|X64"); solutionFile.AppendLine("\t\tDebug|x86 = Debug|x86"); solutionFile.AppendLine("\t\tRelease|Any CPU = Release|Any CPU"); solutionFile.AppendLine("\t\tRelease|Mixed Platforms = Release|Mixed Platforms"); solutionFile.AppendLine("\t\tRelease|X64 = Release|X64"); solutionFile.AppendLine("\t\tRelease|x86 = Release|x86"); solutionFile.AppendLine("\tEndGlobalSection"); #endregion #region GLOBAL SECTION solutionFile.AppendLine("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"); foreach (Guid projectId in solutionProjectList) { string idString = projectId.ToString("B").ToUpperInvariant(); solutionFile.AppendFormat("\t\t{0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|Any CPU.Build.0 = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|X64.ActiveCfg = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|X64.Build.0 = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|x86.ActiveCfg = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Debug|x86.Build.0 = Debug|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|Any CPU.ActiveCfg = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|Any CPU.Build.0 = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|Mixed Platforms.Build.0 = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|X64.ActiveCfg = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|X64.Build.0 = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|x86.ActiveCfg = Release|Any CPU", idString).AppendLine(); solutionFile.AppendFormat("\t\t{0}.Release|x86.Build.0 = Release|Any CPU", idString).AppendLine(); } solutionFile.AppendLine("\tEndGlobalSection"); solutionFile.AppendLine("\tGlobalSection(SolutionProperties) = preSolution"); solutionFile.AppendFormat("\t\tHideSolutionNode = FALSE").AppendLine(); solutionFile.AppendLine("\tEndGlobalSection"); if (testProjects.Count > 0 || startProjects.Count > 0) // put to folder only we have one of these.. { solutionFile.AppendLine("\tGlobalSection(NestedProjects) = preSolution"); foreach (var projectId in otherProjects) { solutionFile.AppendFormat("\t\t{0} = {1}", projectId.ToString("B").ToUpperInvariant(), otherProjectId.ToString("B").ToUpperInvariant()); solutionFile.AppendLine(); } foreach (var projectId in testProjects) { solutionFile.AppendFormat("\t\t{0} = {1}", projectId.ToString("B").ToUpperInvariant(), testProjectId.ToString("B").ToUpperInvariant()); solutionFile.AppendLine(); } solutionFile.AppendLine("\tEndGlobalSection"); } #endregion solutionFile.AppendLine("EndGlobal"); Logger.Trace("Created solution file with {0} projects", solutionProjectList.Count); var generatedSolution = new GeneratedSolution { Content = solutionFile.ToString(), IncludedProjects = solutionProjectList.Count }; return generatedSolution; }
public List<Guid> WalkReferencesRecursively(ProjectSetup projectSetup, ProjectLoader projectLoader, IEnumerable<string> projectLocations, string[] thirdPartyFolders, HashSet<string> usedThirdParties) { List<Guid> completeReferences = new List<Guid>(); foreach (string projectLocation in projectLocations) { VSProject project = projectLoader.LoadProject(projectSetup, projectLocation); List<Guid> dependentReferences = WalkReferencesRecursively(projectSetup, projectLoader, project, thirdPartyFolders, usedThirdParties); dependentReferences.Add(project.ProjectId); foreach (Guid dependentReference in dependentReferences) { if (!completeReferences.Contains(dependentReference)) completeReferences.Add(dependentReference); } } return completeReferences; }
private void ResolveProject(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, VSProjectReference reference, List<VSProject> referencedProjects) { VSProject vsProject; if (reference.IsProjectReference) { // resolve by ID vsProject = projectLoader.GetProjectById(reference.ProjectReferenceId); } else if (reference.IsSilverlightReference) { vsProject = projectLoader.GetProjectById(reference.ProjectReferenceId); } else { // resolve by output path vsProject = projectLoader.GetProjectByOutput(reference.ResolvedHintPath); } if (vsProject != null) { referencedProjects.Add(vsProject); } else { // fall back scenario, check assembly name in current project output path string outputDirectory = Path.GetDirectoryName(project.ResolvedOutput) ?? "."; string currentFolderAssembly = Path.Combine(outputDirectory, reference.ResolvedInclude) + ".dll"; vsProject = projectLoader.GetProjectByOutput(currentFolderAssembly); if (vsProject== null) { currentFolderAssembly = Path.Combine(outputDirectory, reference.ResolvedInclude) + ".exe"; vsProject = projectLoader.GetProjectByOutput(currentFolderAssembly); } if (vsProject == null) { if (projectSetup.WhenReferenceNotResolved == ProjectSetupBehavior.Fail) { throw new SolutionGeneratorException( "Reference {0} was not resolved. {3}Project {1}. {3}Expected location = {2}{3}", reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, Environment.NewLine); } if (projectSetup.WhenReferenceNotResolved == ProjectSetupBehavior.Warn) { Logger.Warn( "Reference {0} was not resolved. {3}Project {1}. {3}Expected location = {2}{3}", reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, Environment.NewLine); } } else { if (projectSetup.WhenReferenceResolvedInDifferentLocation == ProjectSetupBehavior.Fail) { throw new SolutionGeneratorException( "Reference {0} was not resolved. {4}Project {1}. {4}Expected location = {2}{4}However it was found in project output folder {3}.{4}", reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, outputDirectory, Environment.NewLine); } if (projectSetup.WhenReferenceResolvedInDifferentLocation == ProjectSetupBehavior.Warn) { Logger.Warn( "Reference {0} was not resolved. {4}Project {1}. {4}Expected location = {2}{4}However it was found in project output folder {3}.{4}", reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, outputDirectory, Environment.NewLine); } } } }
private List<Guid> GetCurrentProjectReferences(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, HashSet<string> thirdPartyFileMap, HashSet<string> usedThirdParties, List<Guid> checkedProjects) { ReferenceCacheItem cacheItem; if (!ProjectReferenceCache.TryGetValue(project.ProjectId, out cacheItem)) { if (checkedProjects.Contains(project.ProjectId)) { StringBuilder builder = new StringBuilder(); for (int i = checkedProjects.Count - 1; i >= 0; i--) { Guid checkedProject = checkedProjects[i]; builder.Insert(0, projectLoader.GetProjectById(checkedProject).ProjectFileLocation + Environment.NewLine); if (checkedProject == project.ProjectId) break; } builder.AppendLine(project.ProjectFileLocation); throw new SolutionGeneratorException("Circular reference detected! {1}Projects: {1}{0}", builder, Environment.NewLine); } checkedProjects.Add(project.ProjectId); cacheItem = new ReferenceCacheItem { References = new List<Guid>(), UsedThirdParties = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase) }; if (project.References != null) { List<VSProject> referencedProjects = new List<VSProject>(); foreach (VSProjectReference reference in project.References) { if (thirdPartyFileMap.Contains(reference.ResolvedHintPath)) { cacheItem.UsedThirdParties.Add(reference.ResolvedHintPath); continue; } if (SystemReferenceFileMap.Contains(reference.ResolvedInclude)) { continue; } if (reference.ResolvedInclude.StartsWith("Microsoft.", StringComparison.InvariantCultureIgnoreCase)) { continue; } ResolveProject(projectSetup, projectLoader, project, reference, referencedProjects); } foreach (VSProject referencedProject in referencedProjects) { if (!cacheItem.References.Contains(referencedProject.ProjectId)) cacheItem.References.Add(referencedProject.ProjectId); } } //cacheItem.UsedThirdParties.UnionWith(usedThirdParties); ProjectReferenceCache.Add(project.ProjectId, cacheItem); } usedThirdParties.UnionWith(cacheItem.UsedThirdParties); return cacheItem.References; }
public List<Guid> GetProjectDependencies(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, string[] thirdPartyFolders, HashSet<string> usedThirdParties) { HashSet<string> thirdPartyFileMap; if (thirdPartyFolders != null && thirdPartyFolders.Length > 0) { string key = string.Join(":", thirdPartyFolders); if (!ThirdPartyFileCache.TryGetValue(key, out thirdPartyFileMap)) { thirdPartyFileMap = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase); List<string> thirdPartyFiles = FileSearcher.Scan("*.dll", thirdPartyFolders); thirdPartyFileMap.UnionWith(thirdPartyFiles); ThirdPartyFileCache.Add(key, thirdPartyFileMap); } } else { thirdPartyFileMap = new HashSet<string>(); } List<Guid> checkedProjects = new List<Guid>(); var completeReferences = GetCurrentProjectReferences(projectSetup, projectLoader, project, thirdPartyFileMap, usedThirdParties, checkedProjects); return completeReferences; }