Esempio n. 1
0
 public Worker(
     Workspace workspace,
     DiagnosticReporter diagnosticReporter,
     PathResolver pathResolver,
     ProjectFileLoaderRegistry projectFileLoaderRegistry,
     ProjectBuildManager buildManager,
     ImmutableArray <string> requestedProjectPaths,
     string baseDirectory,
     ImmutableDictionary <string, string> globalProperties,
     ProjectMap projectMap,
     IProgress <ProjectLoadProgress> progress,
     DiagnosticReportingOptions requestedProjectOptions,
     DiagnosticReportingOptions discoveredProjectOptions,
     bool preferMetadataForReferencesOfDiscoveredProjects)
 {
     _workspace                 = workspace;
     _diagnosticReporter        = diagnosticReporter;
     _pathResolver              = pathResolver;
     _projectFileLoaderRegistry = projectFileLoaderRegistry;
     _buildManager              = buildManager;
     _baseDirectory             = baseDirectory;
     _requestedProjectPaths     = requestedProjectPaths;
     _globalProperties          = globalProperties;
     _projectMap                = projectMap ?? ProjectMap.Create();
     _progress = progress;
     _requestedProjectOptions  = requestedProjectOptions;
     _discoveredProjectOptions = discoveredProjectOptions;
     _preferMetadataForReferencesOfDiscoveredProjects = preferMetadataForReferencesOfDiscoveredProjects;
     _projectIdToFileInfoMap          = new Dictionary <ProjectId, ProjectFileInfo>();
     _pathToDiscoveredProjectInfosMap = new Dictionary <string, ImmutableArray <ProjectInfo> >(PathUtilities.Comparer);
     _projectIdToProjectReferencesMap = new Dictionary <ProjectId, List <ProjectReference> >();
 }
Esempio n. 2
0
            private async Task <ImmutableArray <ProjectInfo> > LoadProjectInfosFromPathAsync(
                string projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
            {
                if (_projectMap.TryGetProjectInfosByProjectPath(projectPath, out var results) ||
                    _pathToDiscoveredProjectInfosMap.TryGetValue(projectPath, out results))
                {
                    return(results);
                }

                var builder = ImmutableArray.CreateBuilder <ProjectInfo>();

                var projectFileInfos = await LoadProjectFileInfosAsync(projectPath, reportingOptions, cancellationToken).ConfigureAwait(false);

                var idsAndFileInfos = new List <(ProjectId id, ProjectFileInfo fileInfo)>();

                foreach (var projectFileInfo in projectFileInfos)
                {
                    var projectId = _projectMap.GetOrCreateProjectId(projectFileInfo);

                    if (_projectIdToFileInfoMap.ContainsKey(projectId))
                    {
                        // There are multiple projects with the same project path and output path. This can happen
                        // if a multi-TFM project does not have unique output file paths for each TFM. In that case,
                        // we'll create a new ProjectId to ensure that the project is added to the workspace.

                        _diagnosticReporter.Report(
                            DiagnosticReportingMode.Log,
                            string.Format(WorkspaceMSBuildResources.Found_project_with_the_same_file_path_and_output_path_as_another_project_0, projectFileInfo.FilePath));

                        projectId = ProjectId.CreateNewId(debugName: projectFileInfo.FilePath);
                    }

                    idsAndFileInfos.Add((projectId, projectFileInfo));
                    _projectIdToFileInfoMap.Add(projectId, projectFileInfo);
                }

                // If this project resulted in more than a single project, a discrimator (e.g. TFM) should be
                // added to the project name.
                var addDiscriminator = idsAndFileInfos.Count > 1;

                foreach (var(id, fileInfo) in idsAndFileInfos)
                {
                    var projectInfo = await CreateProjectInfoAsync(fileInfo, id, addDiscriminator, cancellationToken).ConfigureAwait(false);

                    builder.Add(projectInfo);
                    _projectMap.AddProjectInfo(projectInfo);
                }

                results = builder.ToImmutable();

                _pathToDiscoveredProjectInfosMap.Add(projectPath, results);

                return(results);
            }
Esempio n. 3
0
        /// <summary>
        /// Loads the <see cref="ProjectInfo"/> from the specified project file and all referenced projects.
        /// The first <see cref="ProjectInfo"/> in the result corresponds to the specified project file.
        /// </summary>
        /// <param name="projectFilePath">The path to the project file to be loaded. This may be an absolute path or a path relative to the
        /// current working directory.</param>
        /// <param name="projectMap">An optional <see cref="ProjectMap"/> that will be used to resolve project references to existing projects.
        /// This is useful when populating a custom <see cref="Workspace"/>.</param>
        /// <param name="progress">An optional <see cref="IProgress{T}"/> that will receive updates as the project is loaded.</param>
        /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> to allow cancellation of this operation.</param>
        public async Task <ImmutableArray <ProjectInfo> > LoadProjectInfoAsync(
            string projectFilePath,
            ProjectMap projectMap = null,
            IProgress <ProjectLoadProgress> progress = null,
            CancellationToken cancellationToken      = default)
        {
            if (projectFilePath == null)
            {
                throw new ArgumentNullException(nameof(projectFilePath));
            }

            var requestedProjectOptions = DiagnosticReportingOptions.ThrowForAll;

            var reportingMode = GetReportingModeForUnrecognizedProjects();

            var discoveredProjectOptions = new DiagnosticReportingOptions(
                onPathFailure: reportingMode,
                onLoaderFailure: reportingMode);

            var buildManager = new ProjectBuildManager(_properties);

            var worker = new Worker(
                _workspace,
                _diagnosticReporter,
                _pathResolver,
                _projectFileLoaderRegistry,
                buildManager,
                requestedProjectPaths: ImmutableArray.Create(projectFilePath),
                baseDirectory: Directory.GetCurrentDirectory(),
                globalProperties: _properties,
                projectMap,
                progress,
                requestedProjectOptions,
                discoveredProjectOptions,
                this.LoadMetadataForReferencedProjects);

            return(await worker.LoadAsync(cancellationToken).ConfigureAwait(false));
        }
Esempio n. 4
0
            private async Task <ImmutableArray <ProjectFileInfo> > LoadProjectFileInfosAsync(string projectPath, DiagnosticReportingOptions reportingOptions, CancellationToken cancellationToken)
            {
                if (!_projectFileLoaderRegistry.TryGetLoaderFromProjectPath(projectPath, reportingOptions.OnLoaderFailure, out var loader))
                {
                    return(ImmutableArray <ProjectFileInfo> .Empty); // Failure should already be reported.
                }

                var projectFile = await DoOperationAndReportProgressAsync(
                    ProjectLoadOperation.Evaluate,
                    projectPath,
                    targetFramework : null,
                    () => loader.LoadProjectFileAsync(projectPath, _buildManager, cancellationToken)
                    ).ConfigureAwait(false);

                // If there were any failures during load, we won't be able to build the project. So, bail early with an empty project.
                if (projectFile.Log.HasFailure)
                {
                    _diagnosticReporter.Report(projectFile.Log);

                    return(ImmutableArray.Create(
                               ProjectFileInfo.CreateEmpty(loader.Language, projectPath, projectFile.Log)));
                }

                var projectFileInfos = await DoOperationAndReportProgressAsync(
                    ProjectLoadOperation.Build,
                    projectPath,
                    targetFramework : null,
                    () => projectFile.GetProjectFileInfosAsync(cancellationToken)
                    ).ConfigureAwait(false);

                var results = ImmutableArray.CreateBuilder <ProjectFileInfo>(projectFileInfos.Length);

                foreach (var projectFileInfo in projectFileInfos)
                {
                    // If any diagnostics were logged during build, we'll carry on and try to produce a meaningful project.
                    if (!projectFileInfo.Log.IsEmpty)
                    {
                        _diagnosticReporter.Report(projectFileInfo.Log);
                    }

                    results.Add(projectFileInfo);
                }

                return(results.MoveToImmutable());
            }