public async Task AnalyzeProjectAsync(ICollection <Project> projects, CancellationToken cancellationToken = default(CancellationToken))
        {
            var buildSucceeded = await _builder.BuildAsync(projects).ConfigureAwait(false);

            if (!buildSucceeded)
            {
                throw new PortabilityAnalyzerException(LocalizedStrings.UnableToBuildProject);
            }

            // TODO: Add option to include everything in output, not just build artifacts
            var targetAssemblies = new ConcurrentBag <string>();

            var referencedNuGetPackages = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (var project in projects)
            {
                var output = await _builder.GetBuildOutputFilesAsync(project).ConfigureAwait(false);

                // Could not find any output files for this. Skip it.
                if (output == null)
                {
                    continue;
                }

                foreach (var file in output)
                {
                    targetAssemblies.Add(file);
                }

                referencedNuGetPackages.UnionWith(GetPackageReferences(project));
            }

            if (!targetAssemblies.Any())
            {
                throw new PortabilityAnalyzerException(LocalizedStrings.FailedToLocateBuildOutputDir);
            }

            var result = await _analyzer.WriteAnalysisReportsAsync(targetAssemblies, referencedNuGetPackages, _reportWriter, true).ConfigureAwait(false);

            var sourceItems = await Task.Run(() => _sourceLineMapper.GetSourceInfo(targetAssemblies, result)).ConfigureAwait(false);

            var dictionary = new ConcurrentBag <CalculatedProject>();

            foreach (var project in projects)
            {
                var outputFiles = await _builder.GetBuildOutputFilesAsync(project).ConfigureAwait(false);

                var hierarchy = await _projectMapper.GetVsHierarchyAsync(project).ConfigureAwait(false);

                dictionary.Add(new CalculatedProject(project, hierarchy, outputFiles ?? Enumerable.Empty <string>()));
            }

            await _errorList.DisplaySourceItemsAsync(sourceItems, dictionary.ToArray()).ConfigureAwait(false);
        }
        public async Task <ProjectInfo> DiscoverAsync(
            bool shouldBuildIfNeeded,
            string configuration,
            string targetFramework,
            string project,
            string assembly,
            string connectionString,
            string connectionStringName)
        {
            if (assembly == null)
            {
                var projectFile = FindProjectFile(project);
                if (projectFile == null)
                {
                    throw new ProjectNotFoundException("No assembly provided and project file could not be found.");
                }

                using (var projectFileStream = projectFile.CreateReadStream())
                {
                    var projectDoc = await XDocument.LoadAsync(projectFileStream, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);

                    var assemblyName = projectDoc.Root.Descendants("AssemblyName")
                                       .Select(n => n.Value)
                                       .SingleOrDefault() ?? Path.GetFileNameWithoutExtension(projectFile.Name);

                    targetFramework = FindTargetFramework(projectDoc, targetFramework);
                    configuration   = configuration ?? "Debug";

                    if (shouldBuildIfNeeded)
                    {
                        await _projectBuilder.BuildAsync(projectFile, configuration, targetFramework).ConfigureAwait(false);
                    }

                    var projectDir   = Path.GetDirectoryName(projectFile.PhysicalPath);
                    var assemblyFile = _fileSystem.GetFile(Path.Combine(projectDir, "bin", configuration, targetFramework, $"{assemblyName}.dll"));
                    if (!assemblyFile.Exists)
                    {
                        throw new ProjectNotFoundException("Assembly containing migrations could not be found.");
                    }

                    assembly = assemblyFile.PhysicalPath;
                }

                connectionString = connectionString ?? FindConnectionString(projectFile, connectionStringName);
            }

            return(new ProjectInfo(
                       Assembly.LoadFrom(assembly),
                       connectionString));
        }