using Microsoft.Build.Construction; using Microsoft.Build.Exceptions; using System; using System.Collections.Generic; using System.Linq; using Semmle.Util; namespace Semmle.Autobuild { /// /// A solution file, extension .sln. /// public interface ISolution : IProjectOrSolution { /// /// Solution configurations. /// IEnumerable Configurations { get; } /// /// The default configuration name, e.g. "Release" /// string DefaultConfigurationName { get; } /// /// The default platform name, e.g. "x86" /// string DefaultPlatformName { get; } /// /// Gets the "best" tools version for this solution. /// If there are several versions, because the project files /// are inconsistent, then pick the highest/latest version. /// If no tools versions are present, return 0.0.0.0. /// Version ToolsVersion { get; } } /// /// A solution file on the filesystem, read using Microsoft.Build. /// class Solution : ProjectOrSolution, ISolution { readonly SolutionFile solution; readonly IEnumerable includedProjects; public override IEnumerable IncludedProjects => includedProjects; public IEnumerable Configurations => solution == null ? Enumerable.Empty() : solution.SolutionConfigurations; public string DefaultConfigurationName => solution == null ? "" : solution.GetDefaultConfigurationName(); public string DefaultPlatformName => solution == null ? "" : solution.GetDefaultPlatformName(); public Solution(Autobuilder builder, string path) : base(builder, path) { try { solution = SolutionFile.Parse(FullPath); includedProjects = solution.ProjectsInOrder. Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat). Select(p => builder.Actions.GetFullPath(FileUtils.ConvertToNative(p.AbsolutePath))). Select(p => new Project(builder, p)). ToArray(); } catch (InvalidProjectFileException) { // We allow specifying projects as solutions in lgtm.yml, so model // that scenario as a solution with just that one project includedProjects = new[] { new Project(builder, path) }; } } IEnumerable ToolsVersions => includedProjects.Where(p => p.ValidToolsVersion).Select(p => p.ToolsVersion); public Version ToolsVersion => ToolsVersions.Any() ? ToolsVersions.Max() : new Version(); } }