Esempio n. 1
0
        /// <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);
        }
        public async Task <PackageAnalysisState> AnalyzeAsync(IProject project, PackageAnalysisState state, CancellationToken token)
        {
            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (state is null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            var components = await project.GetComponentsAsync(token).ConfigureAwait(false);

            // This reference only needs added to ASP.NET Core exes
            if (!(components.HasFlag(ProjectComponents.AspNetCore) &&
                  project.OutputType == ProjectOutputType.Exe &&
                  !project.TargetFrameworks.Any(tfm => _tfmComparer.Compare(tfm, TargetFrameworkMoniker.NetCoreApp30) < 0)))
            {
                return(state);
            }

            var references = await project.GetNuGetReferencesAsync(token).ConfigureAwait(false);

            if (references.IsTransitivelyAvailable(NewtonsoftPackageName))
            {
                _logger.LogDebug("{PackageName} already referenced transitively", NewtonsoftPackageName);
                return(state);
            }

            var packageReferences = references.PackageReferences.Where(r => !state.PackagesToRemove.Contains(r));

            if (!packageReferences.Any(r => NewtonsoftPackageName.Equals(r.Name, StringComparison.OrdinalIgnoreCase)))
            {
                var newtonsoftPackage = await _packageLoader.GetLatestVersionAsync(NewtonsoftPackageName, false, null, token).ConfigureAwait(false);

                if (newtonsoftPackage is not null)
                {
                    _logger.LogInformation("Reference to Newtonsoft package ({NewtonsoftPackageName}, version {NewtonsoftPackageVersion}) needs added", NewtonsoftPackageName, newtonsoftPackage.Version);
                    state.PackagesToAdd.Add(newtonsoftPackage);
                }
                else
                {
                    _logger.LogWarning("Newtonsoft NuGet package reference cannot be added because the package cannot be found");
                }
            }
            else
            {
                _logger.LogDebug("Reference to Newtonsoft package ({NewtonsoftPackageName}) already exists", NewtonsoftPackageName);
            }

            return(state);
        }
Esempio n. 3
0
        public async Task AnalyzeAsync(IProject project, IDependencyAnalysisState state, CancellationToken token)
        {
            if (project is null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            if (state is null)
            {
                throw new ArgumentNullException(nameof(state));
            }

            var components = await project.GetComponentsAsync(token).ConfigureAwait(false);

            // This reference only needs added to ASP.NET Core exes
            if (!(components.HasFlag(ProjectComponents.AspNetCore) &&
                  project.OutputType == ProjectOutputType.Exe &&
                  !state.TargetFrameworks.Any(tfm => _tfmComparer.Compare(tfm, TargetFrameworkMoniker.NetCoreApp30) < 0)))
            {
                return;
            }

            if (await _transitiveIdentifier.IsTransitiveDependencyAsync(NewtonsoftPackageName, project, token).ConfigureAwait(false))
            {
                _logger.LogDebug("{PackageName} already referenced transitively", NewtonsoftPackageName);
                return;
            }

            if (!state.Packages.Any(r => NewtonsoftPackageName.Equals(r.Name, StringComparison.OrdinalIgnoreCase)))
            {
                var newtonsoftPackage = await _packageLoader.GetLatestVersionAsync(NewtonsoftPackageName, state.TargetFrameworks, new(), token).ConfigureAwait(false);

                if (newtonsoftPackage is not null)
                {
                    var logMessage = SR.Format("Reference to Newtonsoft package ({0}, version {1}) needs to be added", NewtonsoftPackageName, newtonsoftPackage.Version);
                    _logger.LogInformation(logMessage);
                    state.Packages.Add(newtonsoftPackage, new OperationDetails {
                        Risk = BuildBreakRisk.None, Details = new[] { logMessage }
                    });
                }
                else
                {
                    _logger.LogWarning("Newtonsoft NuGet package reference cannot be added because the package cannot be found");
                }
            }
            else
            {
                _logger.LogDebug("Reference to Newtonsoft package ({NewtonsoftPackageName}) already exists", NewtonsoftPackageName);
            }
        }