/// <summary> /// Chooses the most likely target TFM a project should be retargeted to based on its style, output type, dependencies, and /// the user's preference of current or LTS. /// </summary> public TargetFrameworkMoniker SelectTFM(IProject project) { if (project is null) { throw new ArgumentNullException(nameof(project)); } var tfmName = GetNetStandardTFM(project); // Projects with web components or an Exe output type should use app TFMs if (project.Components.HasFlag(ProjectComponents.AspNet) || project.Components.HasFlag(ProjectComponents.AspNetCore) || project.OutputType == ProjectOutputType.Exe) { tfmName = AppTFMBase; } // Projects with Windows Desktop components or a WinExe output type should use a -windows suffix if (project.Components.HasFlag(ProjectComponents.WindowsDesktop) || project.OutputType == ProjectOutputType.WinExe) { tfmName = $"{AppTFMBase}{WindowsSuffix}"; if (project.Components.HasFlag(ProjectComponents.WinRT)) { // TODO: Default to this version to ensure everything is supported. tfmName += "10.0.19041.0"; } } _logger.LogDebug("Considering TFM {TFM} for project {Project} based on its style and output type ({ProjectStyle}, {ProjectOutputType})", tfmName, project.FilePath, project.Components, project.OutputType); // If the project depends on another project with a higher version NetCore or NetStandard TFM, // use that TFM instead. var tfm = new TargetFrameworkMoniker(tfmName); foreach (var dep in project.ProjectReferences) { try { if (_tfmComparer.IsCompatible(tfm, dep.TFM)) { continue; } if (dep.TFM.IsNetCore || dep.TFM.IsNetStandard) { tfm = dep.TFM; _logger.LogDebug("Considering TFM {TFM} for project {Project} based on its dependency on {DepProject}", tfm, project.FilePath, dep.FilePath); } } catch (UpgradeException) { _logger.LogWarning($"Unable to determine TFM for dependency {dep.FilePath}; TFM for {project.FilePath} may not be correct."); } } _logger.LogDebug("Recommending TFM {TFM} for project {Project}", tfm, project.FilePath); // Ensure we don't downgrade a project return(_tfmComparer.Compare(project.TFM, tfm) > 0 ? project.TFM : tfm); }
// Consider a project completely upgraded if it is SDK-style and has a TFM equal to (or greater then) the expected one private async ValueTask <bool> IsCompletedAsync(IUpgradeContext context, IProject project, CancellationToken token) { if (!project.GetFile().IsSdk) { return(false); } var expectedTfm = await _tfmSelector.SelectTargetFrameworkAsync(project, token).ConfigureAwait(false); return(project.TargetFrameworks.Any(tfm => _tfmComparer.IsCompatible(tfm, expectedTfm))); }
// Consider a project completely upgraded if it is SDK-style and has a TFM equal to (or greater then) the expected one private bool IsCompleted(IUpgradeContext context, IProject project) => project.GetFile().IsSdk&& _tfmComparer.IsCompatible(project.TFM, _tfmSelector.SelectTFM(project));