/// <summary> /// Adds a project to an existing Roslyn workspace. /// </summary> /// <param name="analyzer">The Buildalyzer project analyzer.</param> /// <param name="workspace">A Roslyn workspace.</param> /// <param name="addProjectReferences"> /// <c>true</c> to add projects to the workspace for project references that exist in the same /// <see cref="AnalyzerManager" />. /// </param> /// <returns>The newly added Roslyn project.</returns> public static Project AddToWorkspace(this ProjectAnalyzer analyzer, AdhocWorkspace workspace, bool addProjectReferences = false) { if (analyzer == null) { throw new ArgumentNullException(nameof(analyzer)); } if (workspace == null) { throw new ArgumentNullException(nameof(workspace)); } // Get or create an ID for this project var projectGuid = analyzer.CompiledProject?.GetPropertyValue("ProjectGuid"); var projectId = !string.IsNullOrEmpty(projectGuid) && Guid.TryParse(analyzer.CompiledProject?.GetPropertyValue("ProjectGuid"), out var projectIdGuid) ? ProjectId.CreateFromSerialized(projectIdGuid) : ProjectId.CreateNewId(); // Create and add the project var projectInfo = GetProjectInfo(analyzer, workspace, projectId); var solution = workspace.CurrentSolution.AddProject(projectInfo); // Check if this project is referenced by any other projects in the workspace foreach (var existingProject in solution.Projects.ToArray()) { if (!existingProject.Id.Equals(projectId) && analyzer.Manager.Projects.TryGetValue(existingProject.FilePath, out var existingAnalyzer) && (existingAnalyzer.GetProjectReferences()?.Contains(analyzer.ProjectFilePath) ?? false)) { // Add the reference to the existing project var projectReference = new ProjectReference(projectId); solution = solution.AddProjectReference(existingProject.Id, projectReference); } } // Apply solution changes if (!workspace.TryApplyChanges(solution)) { throw new InvalidOperationException("Could not apply workspace solution changes"); } // Add any project references not already added if (addProjectReferences) { foreach (var referencedAnalyzer in GetReferencedAnalyzerProjects(analyzer)) { // Check if the workspace contains the project inside the loop since adding one might also add this one due to transitive references if (!workspace.CurrentSolution.Projects.Any(x => x.FilePath == referencedAnalyzer.ProjectFilePath)) { AddToWorkspace(referencedAnalyzer, workspace, addProjectReferences); } } } // Find and return this project return(workspace.CurrentSolution.GetProject(projectId)); }
/// <summary> /// Gets a Roslyn workspace for the analyzed project. /// </summary> /// <param name="analyzer">The Buildalyzer project analyzer.</param> /// <param name="addProjectReferences"><c>true</c> to add projects to the workspace for project references that exist in the same <see cref="AnalyzerManager"/>.</param> /// <returns>A Roslyn workspace.</returns> public static AdhocWorkspace GetWorkspace(this ProjectAnalyzer analyzer, bool addProjectReferences = false) { if (analyzer == null) { throw new ArgumentNullException(nameof(analyzer)); } AdhocWorkspace workspace = new AdhocWorkspace(); AddToWorkspace(analyzer, workspace, addProjectReferences); return(workspace); }
public ProjectAnalyzer GetProject(string projectFilePath) { if (projectFilePath == null) { throw new ArgumentNullException(nameof(projectFilePath)); } // Normalize as .sln uses backslash regardless of OS the sln is created on projectFilePath = projectFilePath.Replace('\\', Path.DirectorySeparatorChar); projectFilePath = ValidatePath(projectFilePath, true); if (_projects.TryGetValue(projectFilePath, out ProjectAnalyzer project)) { return(project); } project = new ProjectAnalyzer(this, projectFilePath); _projects.Add(projectFilePath, project); return(project); }
private static ProjectInfo GetProjectInfo(ProjectAnalyzer analyzer, AdhocWorkspace workspace, ProjectId projectId) { string projectName = Path.GetFileNameWithoutExtension(analyzer.ProjectFilePath); string languageName = GetLanguageName(analyzer.ProjectFilePath); ProjectInfo projectInfo = ProjectInfo.Create( projectId, VersionStamp.Create(), projectName, projectName, languageName, filePath: analyzer.ProjectFilePath, outputFilePath: analyzer.CompiledProject?.GetPropertyValue("TargetPath"), documents: GetDocuments(analyzer, projectId), projectReferences: GetExistingProjectReferences(analyzer, workspace), metadataReferences: GetMetadataReferences(analyzer), compilationOptions: CreateCompilationOptions(analyzer.Project, languageName)); return(projectInfo); }
private static IEnumerable <ProjectAnalyzer> GetReferencedAnalyzerProjects(ProjectAnalyzer analyzer) => analyzer.GetProjectReferences() ?.Select(x => analyzer.Manager.Projects.TryGetValue(x, out ProjectAnalyzer a) ? a : null)
private static IEnumerable <ProjectReference> GetExistingProjectReferences(ProjectAnalyzer analyzer, AdhocWorkspace workspace) => analyzer.GetProjectReferences() ?.Select(x => workspace.CurrentSolution.Projects.FirstOrDefault(y => y.FilePath == x)) .Where(x => x != null) .Select(x => new ProjectReference(x.Id)) ?? Array.Empty <ProjectReference>();