diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FeedManager.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FeedManager.cs index 1d5523a983cb..0cbf106df38a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FeedManager.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/FeedManager.cs @@ -60,17 +60,12 @@ internal sealed partial class FeedManager : IDisposable /// public ImmutableHashSet InheritedFeeds => AllFeeds.Except(ExplicitFeeds).ToImmutableHashSet(); - private readonly Lazy<(bool, ImmutableHashSet)> lazyReachableExplicitFeeds; - - /// - /// Gets whether there was a timeout when checking the reachability of the explicitly configured NuGet feeds. - /// - public bool ExplicitFeedTimeout => lazyReachableExplicitFeeds.Value.Item1; + private readonly Lazy> lazyReachableExplicitFeeds; /// /// Gets the list of reachable NuGet feeds that are explicitly configured. /// - public ImmutableHashSet ReachableExplicitFeeds => lazyReachableExplicitFeeds.Value.Item2; + public ImmutableHashSet ReachableExplicitFeeds => lazyReachableExplicitFeeds.Value; private readonly Lazy> lazyReachableFeeds; /// @@ -96,15 +91,11 @@ public FeedManager(ILogger logger, IDotNet dotnet, DependabotProxy? dependabotPr lazyExplicitFeeds = new Lazy>(GetExplicitFeeds); lazyAllFeeds = new Lazy>(GetAllFeeds); - lazyReachableExplicitFeeds = new Lazy<(bool, ImmutableHashSet)>(() => - { - var timeout = CheckSpecifiedFeeds(ExplicitFeeds, out var reachableFeeds); - return (timeout, reachableFeeds); - }); + lazyReachableExplicitFeeds = new Lazy>(() => CheckSpecifiedFeeds(ExplicitFeeds)); lazyReachableFeeds = new Lazy>(() => { // Inherited feeds should only be used, if they are indeed reachable (as they may be environment specific). - CheckSpecifiedFeeds(InheritedFeeds, out var reachableInheritedFeeds); + var reachableInheritedFeeds = CheckSpecifiedFeeds(InheritedFeeds); return ReachableExplicitFeeds.Union(reachableInheritedFeeds).ToImmutableHashSet(); }); lazyReachableFallbackFeeds = new Lazy>(() => @@ -271,7 +262,7 @@ private static async Task ExecuteGetRequest(string address, return await httpClient.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, cancellationToken); } - private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, out bool isTimeout) + private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount) { logger.LogInfo($"Checking if NuGet feed '{feed}' is reachable..."); @@ -304,8 +295,6 @@ private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, using HttpClient client = new(httpClientHandler); - isTimeout = false; - for (var i = 0; i < tryCount; i++) { using var cts = new CancellationTokenSource(); @@ -335,7 +324,6 @@ private bool IsFeedReachable(string feed, int timeoutMilliSeconds, int tryCount, } logger.LogWarning($"Didn't receive answer from NuGet feed '{feed}'. Tried it {tryCount} times."); - isTimeout = true; return false; } @@ -359,12 +347,8 @@ private HashSet GetExcludedFeeds() /// Checks that we can connect to the specified NuGet feeds. /// /// The set of package feeds to check. - /// The list of feeds that were reachable. - /// - /// True if there is a timeout when trying to reach the feeds (excluding any feeds that are configured - /// to be excluded from the check) or false otherwise. - /// - private bool CheckSpecifiedFeeds(ImmutableHashSet feeds, out ImmutableHashSet reachableFeeds) + /// The list of feeds that were reachable. + private ImmutableHashSet CheckSpecifiedFeeds(ImmutableHashSet feeds) { // Exclude any feeds from the feed check that are configured by the corresponding environment variable. // These feeds are always assumed to be reachable. @@ -380,12 +364,10 @@ private bool CheckSpecifiedFeeds(ImmutableHashSet feeds, out ImmutableHa return true; }).ToHashSet(); - var reachable = GetReachableNuGetFeeds(feedsToCheck, isFallback: false, out var isTimeout); + var reachable = GetReachableNuGetFeeds(feedsToCheck, isFallback: false); // Always consider feeds excluded for the reachability check as reachable. - reachableFeeds = reachable.Union(feeds.Where(feed => excludedFeeds.Contains(feed))).ToImmutableHashSet(); - - return isTimeout; + return reachable.Union(feeds.Where(feed => excludedFeeds.Contains(feed))).ToImmutableHashSet(); } /// @@ -398,7 +380,7 @@ public bool IsDefaultFeedReachable() if (CheckNugetFeedResponsiveness) { var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback: false); - return IsFeedReachable(PublicNugetOrgFeed, initialTimeout, tryCount, out var _); + return IsFeedReachable(PublicNugetOrgFeed, initialTimeout, tryCount); } return true; @@ -409,22 +391,15 @@ public bool IsDefaultFeedReachable() /// /// The feeds to check. /// Whether the feeds are fallback feeds or not. - /// Whether a timeout occurred while checking the feeds. /// The list of feeds that could be reached. - private List GetReachableNuGetFeeds(HashSet feedsToCheck, bool isFallback, out bool isTimeout) + private List GetReachableNuGetFeeds(HashSet feedsToCheck, bool isFallback) { var fallbackStr = isFallback ? "fallback " : ""; logger.LogInfo($"Checking {fallbackStr}NuGet feed reachability on feeds: {string.Join(", ", feedsToCheck.OrderBy(f => f))}"); var (initialTimeout, tryCount) = GetFeedRequestSettings(isFallback); - var timeout = false; var reachableFeeds = feedsToCheck - .Where(feed => - { - var reachable = IsFeedReachable(feed, initialTimeout, tryCount, out var feedTimeout); - timeout |= feedTimeout; - return reachable; - }) + .Where(feed => IsFeedReachable(feed, initialTimeout, tryCount)) .ToList(); if (reachableFeeds.Count == 0) @@ -436,7 +411,6 @@ private List GetReachableNuGetFeeds(HashSet feedsToCheck, bool i logger.LogInfo($"Reachable {fallbackStr}NuGet feeds: {string.Join(", ", reachableFeeds.OrderBy(f => f))}"); } - isTimeout = timeout; return reachableFeeds; } @@ -460,7 +434,7 @@ private List GetReachableFallbackNugetFeeds() } } - return GetReachableNuGetFeeds(fallbackFeeds, isFallback: true, out var _); + return GetReachableNuGetFeeds(fallbackFeeds, isFallback: true); } private ImmutableHashSet GetExplicitFeeds() diff --git a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs index aeedbc176867..109d050f8786 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.DependencyFetching/NugetPackageRestorer.cs @@ -127,19 +127,8 @@ public HashSet Restore() compilationInfoContainer.CompilationInfos.Add(("Inherited NuGet feed count", inheritedFeeds.Count.ToString())); } - var allExplicitReachable = explicitFeeds.Count == feedManager.ReachableExplicitFeeds.Count; - EmitUnreachableFeedsDiagnostics(allExplicitReachable); - - if (feedManager.ExplicitFeedTimeout) - { - // If we experience a timeout, we use this fallback. - // todo: we could also check the reachability of the inherited nuget feeds, but to use those in the fallback we would need to handle authentication too. - var unresponsiveMissingPackageLocation = DownloadMissingPackages([]); - return unresponsiveMissingPackageLocation is null - ? [] - : [unresponsiveMissingPackageLocation]; - } - + var unreachableExplicitFeeds = explicitFeeds.Except(feedManager.ReachableExplicitFeeds).ToImmutableHashSet(); + EmitFeedReachabilityDiagnostics(unreachableExplicitFeeds); } try @@ -547,25 +536,31 @@ private void TryChangeProjectFile(DirectoryInfo projectDir, Regex pattern, strin } /// - /// If is `false`, logs this and emits a diagnostic. + /// If is not empty, logs this and emits a diagnostic. /// Adds a `CompilationInfos` entry either way. /// - /// Whether all feeds were reachable or not. - private void EmitUnreachableFeedsDiagnostics(bool allFeedsReachable) + /// The feeds that were not reachable. + private void EmitFeedReachabilityDiagnostics(ImmutableHashSet unreachableFeeds) { - if (!allFeedsReachable) + if (unreachableFeeds.Count > 0) { - logger.LogWarning("Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis."); + var orderedUnreachableFeeds = unreachableFeeds.OrderBy(feed => feed).ToList(); + var unreachableFeedList = string.Join(", ", orderedUnreachableFeeds); + logger.LogWarning($"Found unreachable NuGet feeds in C# analysis with build-mode 'none': {unreachableFeedList}. This may cause missing dependencies in the analysis."); + compilationInfoContainer.CompilationInfos.Add(("Unreachable NuGet feeds", unreachableFeedList)); diagnosticsWriter.AddEntry(new DiagnosticMessage( Language.CSharp, "buildless/unreachable-feed", - "Found unreachable NuGet feed in C# analysis with build-mode 'none'", + "Found unreachable NuGet feeds in C# analysis with build-mode 'none'", visibility: new DiagnosticMessage.TspVisibility(statusPage: true, cliSummaryTable: true, telemetry: true), - markdownMessage: "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.", + markdownMessage: string.Format( + "Found unreachable NuGet feeds in C# analysis with build-mode 'none':\n\n{0}\n\nThis may cause missing dependencies in the analysis.", + string.Join("\n", orderedUnreachableFeeds.Select(feed => $"- `{feed}`")) + ), severity: DiagnosticMessage.TspSeverity.Note )); } - compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", allFeedsReachable ? "1" : "0")); + compilationInfoContainer.CompilationInfos.Add(("All NuGet feeds reachable", unreachableFeeds.Count == 0 ? "1" : "0")); } private void EmitNugetConfigDiagnostics() @@ -625,14 +620,6 @@ public void Dispose() feedManager.Dispose(); } - /// - /// Returns the full path to a temporary directory with the given subfolder name. - /// - private static string ComputeTempDirectoryPath(string subfolderName) - { - return Path.Join(FileUtils.GetTemporaryWorkingDirectory(out _), subfolderName); - } - /// /// Computes a unique temporary directory path based on the source directory and the subfolder name. /// diff --git a/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.expected b/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.expected index 6d91b2700226..d0b09f83622c 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.expected +++ b/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.expected @@ -1,21 +1,21 @@ -| All NuGet feeds reachable | 1.0 | -| Failed project restore with missing package error | 0.0 | -| Failed project restore with package source error | 0.0 | -| Failed solution restore with missing package error | 0.0 | -| Failed solution restore with package source error | 0.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resource extraction enabled | 1.0 | -| Restored .NET framework variants | 1.0 | -| Restored projects through solution files | 0.0 | -| Solution files on filesystem | 0.0 | -| Source files generated | 2.0 | -| Source files on filesystem | 1.0 | -| Successfully restored project files | 1.0 | -| Successfully restored solution files | 0.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 1 | +| Failed project restore with missing package error | 0 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 1 | +| Resource extraction enabled | 1 | +| Restored .NET framework variants | 1 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 0 | +| Source files generated | 2 | +| Source files on filesystem | 1 | +| Successfully restored project files | 1 | +| Successfully restored solution files | 0 | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.ql b/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.ql index a96c2fd99a69..28898f02fd24 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.ql +++ b/csharp/ql/integration-tests/all-platforms/standalone_resx/CompilationInfo.ql @@ -1,16 +1,9 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and key != "Resolved assembly conflicts" and not key.matches("Compiler diagnostic count for%") and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.expected b/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.expected index 82cf0509d345..94716c3255ae 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.expected +++ b/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.expected @@ -1,21 +1,21 @@ -| All NuGet feeds reachable | 1.0 | -| Failed project restore with missing package error | 0.0 | -| Failed project restore with package source error | 0.0 | -| Failed solution restore with missing package error | 0.0 | -| Failed solution restore with package source error | 0.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 2.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 1.0 | -| Restored projects through solution files | 2.0 | -| Solution files on filesystem | 1.0 | -| Source files generated | 1.0 | -| Source files on filesystem | 2.0 | -| Successfully restored project files | 0.0 | -| Successfully restored solution files | 1.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 1 | +| Failed project restore with missing package error | 0 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 2 | +| Reachable fallback NuGet feed count | 1 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 1 | +| Restored projects through solution files | 2 | +| Solution files on filesystem | 1 | +| Source files generated | 1 | +| Source files on filesystem | 2 | +| Successfully restored project files | 0 | +| Successfully restored solution files | 1 | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.ql b/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.ql index 078e352be4d9..e6dc52674f37 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.ql +++ b/csharp/ql/integration-tests/all-platforms/standalone_slnx/CompilationInfo.ql @@ -1,16 +1,9 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and key != "Resolved assembly conflicts" and not key.matches(["Compiler diagnostic count for%", "Extractor message count for group%"]) and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.expected b/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.expected index 63ddd4903f3e..ee79179d4fae 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.expected +++ b/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.expected @@ -1,21 +1,21 @@ -| All NuGet feeds reachable | 1.0 | -| Failed project restore with missing package error | 0.0 | -| Failed project restore with package source error | 0.0 | -| Failed solution restore with missing package error | 0.0 | -| Failed solution restore with package source error | 0.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 1.0 | -| Restored projects through solution files | 0.0 | -| Solution files on filesystem | 0.0 | -| Source files generated | 1.0 | -| Source files on filesystem | 3.0 | -| Successfully restored project files | 1.0 | -| Successfully restored solution files | 0.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 1.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 1 | +| Failed project restore with missing package error | 0 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 1 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 1 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 0 | +| Source files generated | 1 | +| Source files on filesystem | 3 | +| Successfully restored project files | 1 | +| Successfully restored solution files | 0 | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 1 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.ql b/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.ql index 078e352be4d9..e6dc52674f37 100644 --- a/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.ql +++ b/csharp/ql/integration-tests/all-platforms/standalone_winforms/CompilationInfo.ql @@ -1,16 +1,9 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and key != "Resolved assembly conflicts" and not key.matches(["Compiler diagnostic count for%", "Extractor message count for group%"]) and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.expected index ff0b29da33fa..e8a0b5897082 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.expected @@ -1,22 +1,22 @@ -| All NuGet feeds reachable | 1.0 | -| Failed project restore with missing package error | 0.0 | -| Failed project restore with package source error | 0.0 | -| Failed solution restore with missing package error | 0.0 | -| Failed solution restore with package source error | 0.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resolved assembly conflicts | 0.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 1.0 | -| Restored projects through solution files | 0.0 | -| Solution files on filesystem | 0.0 | -| Source files generated | 0.0 | -| Source files on filesystem | 1.0 | -| Successfully restored project files | 1.0 | -| Successfully restored solution files | 0.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 1 | +| Failed project restore with missing package error | 0 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 1 | +| Resolved assembly conflicts | 0 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 1 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 0 | +| Source files generated | 0 | +| Source files on filesystem | 1 | +| Successfully restored project files | 1 | +| Successfully restored solution files | 0 | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.ql b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.ql index 073ffe3b224d..ae7505a8b0be 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.ql +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_clear/CompilationInfo.ql @@ -1,15 +1,8 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and not key.matches("Compiler diagnostic count for%") and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.expected index 4acd4f54e8a6..c5cb911d3731 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.expected @@ -1,24 +1,25 @@ -| All NuGet feeds reachable | 0.0 | -| Failed project restore with missing package error | 1.0 | -| Failed project restore with package source error | 0.0 | -| Failed solution restore with missing package error | 0.0 | -| Failed solution restore with package source error | 0.0 | -| Fallback nuget restore | 1.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resolved assembly conflicts | 7.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 0.0 | -| Restored projects through solution files | 0.0 | -| Solution files on filesystem | 1.0 | -| Source files generated | 0.0 | -| Source files on filesystem | 1.0 | -| Successfully ran fallback nuget restore | 1.0 | -| Successfully restored project files | 0.0 | -| Successfully restored solution files | 1.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 0 | +| Failed project restore with missing package error | 1 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Fallback nuget restore | 1 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 1 | +| Resolved assembly conflicts | 7 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 0 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 1 | +| Source files generated | 0 | +| Source files on filesystem | 1 | +| Successfully ran fallback nuget restore | 1 | +| Successfully restored project files | 0 | +| Successfully restored solution files | 1 | +| Unreachable NuGet feeds | https://abc.abc/packages/ | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.ql b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.ql index 073ffe3b224d..ae7505a8b0be 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.ql +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error/CompilationInfo.ql @@ -1,15 +1,8 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and not key.matches("Compiler diagnostic count for%") and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.expected index 5a7abcf543c8..680a7960a06c 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.expected @@ -1,17 +1,25 @@ -| All NuGet feeds reachable | 0.0 | -| Fallback nuget restore | 1.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 1.0 | -| Resolved assembly conflicts | 7.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 0.0 | -| Solution files on filesystem | 1.0 | -| Source files generated | 0.0 | -| Source files on filesystem | 1.0 | -| Successfully ran fallback nuget restore | 1.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 0 | +| Failed project restore with missing package error | 1 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Fallback nuget restore | 1 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 1 | +| Resolved assembly conflicts | 7 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 0 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 1 | +| Source files generated | 0 | +| Source files on filesystem | 1 | +| Successfully ran fallback nuget restore | 1 | +| Successfully restored project files | 0 | +| Successfully restored solution files | 1 | +| Unreachable NuGet feeds | https://localhost:53/packages/, https://localhost:80/packages/ | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.ql b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.ql index 073ffe3b224d..ae7505a8b0be 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.ql +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/CompilationInfo.ql @@ -1,15 +1,8 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and not key.matches("Compiler diagnostic count for%") and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/diagnostics.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/diagnostics.expected index bbd2081f4554..074e4bd48ae9 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/diagnostics.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_error_timeout/diagnostics.expected @@ -27,12 +27,12 @@ } } { - "markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.", + "markdownMessage": "Found unreachable NuGet feeds in C# analysis with build-mode 'none':\n\n- `https://localhost:53/packages/`\n- `https://localhost:80/packages/`\n\nThis may cause missing dependencies in the analysis.", "severity": "note", "source": { "extractorName": "csharp", "id": "csharp/autobuilder/buildless/unreachable-feed", - "name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'" + "name": "Found unreachable NuGet feeds in C# analysis with build-mode 'none'" }, "visibility": { "cliSummaryTable": true, diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.expected index 9cc03f2f5372..384d64a59855 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.expected @@ -1,17 +1,25 @@ -| All NuGet feeds reachable | 0.0 | -| Fallback nuget restore | 1.0 | -| Inherited NuGet feed count | 1.0 | -| NuGet feed responsiveness checked | 1.0 | -| Project files on filesystem | 1.0 | -| Reachable fallback NuGet feed count | 2.0 | -| Resolved assembly conflicts | 7.0 | -| Resource extraction enabled | 0.0 | -| Restored .NET framework variants | 0.0 | -| Solution files on filesystem | 1.0 | -| Source files generated | 0.0 | -| Source files on filesystem | 1.0 | -| Successfully ran fallback nuget restore | 1.0 | -| Unresolved references | 0.0 | -| UseWPF set | 0.0 | -| UseWindowsForms set | 0.0 | -| WebView extraction enabled | 1.0 | +| All NuGet feeds reachable | 0 | +| Failed project restore with missing package error | 1 | +| Failed project restore with package source error | 0 | +| Failed solution restore with missing package error | 0 | +| Failed solution restore with package source error | 0 | +| Fallback nuget restore | 1 | +| Inherited NuGet feed count | 1 | +| NuGet feed responsiveness checked | 1 | +| Project files on filesystem | 1 | +| Reachable fallback NuGet feed count | 2 | +| Resolved assembly conflicts | 7 | +| Resource extraction enabled | 0 | +| Restored .NET framework variants | 0 | +| Restored projects through solution files | 0 | +| Solution files on filesystem | 1 | +| Source files generated | 0 | +| Source files on filesystem | 1 | +| Successfully ran fallback nuget restore | 1 | +| Successfully restored project files | 0 | +| Successfully restored solution files | 1 | +| Unreachable NuGet feeds | https://www.nuget.org/api/v2/ | +| Unresolved references | 0 | +| UseWPF set | 0 | +| UseWindowsForms set | 0 | +| WebView extraction enabled | 1 | diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.ql b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.ql index 073ffe3b224d..ae7505a8b0be 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.ql +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/CompilationInfo.ql @@ -1,15 +1,8 @@ import csharp import semmle.code.csharp.commons.Diagnostics -query predicate compilationInfo(string key, float value) { +query predicate compilationInfo(string key, string value) { key != "Resolved references" and not key.matches("Compiler diagnostic count for%") and - exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) | - key = infoKey and - value = infoValue.toFloat() - or - not exists(infoValue.toFloat()) and - key = infoKey + ": " + infoValue and - value = 1 - ) + value = any(Compilation c).getInfo(key) } diff --git a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/diagnostics.expected b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/diagnostics.expected index bbd2081f4554..66867fd38eeb 100644 --- a/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/diagnostics.expected +++ b/csharp/ql/integration-tests/posix/standalone_dependencies_nuget_config_fallback/diagnostics.expected @@ -27,12 +27,12 @@ } } { - "markdownMessage": "Found unreachable NuGet feed in C# analysis with build-mode 'none'. This may cause missing dependencies in the analysis.", + "markdownMessage": "Found unreachable NuGet feeds in C# analysis with build-mode 'none':\n\n- `https://www.nuget.org/api/v2/`\n\nThis may cause missing dependencies in the analysis.", "severity": "note", "source": { "extractorName": "csharp", "id": "csharp/autobuilder/buildless/unreachable-feed", - "name": "Found unreachable NuGet feed in C# analysis with build-mode 'none'" + "name": "Found unreachable NuGet feeds in C# analysis with build-mode 'none'" }, "visibility": { "cliSummaryTable": true, diff --git a/csharp/ql/lib/change-notes/2026-08-18-tsp-nuget-feed-reachability.md b/csharp/ql/lib/change-notes/2026-08-18-tsp-nuget-feed-reachability.md new file mode 100644 index 000000000000..fc391ad6f804 --- /dev/null +++ b/csharp/ql/lib/change-notes/2026-08-18-tsp-nuget-feed-reachability.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* C# analysis with build mode `none` now lists unreachable explicitly configured NuGet feeds in both the extraction warning and the tool status page note. This makes it easier to identify feeds that may cause dependencies to be missing from the analysis.