This commit is contained in:
StellaOps Bot
2025-12-09 00:20:52 +02:00
parent 3d01bf9edc
commit bc0762e97d
261 changed files with 14033 additions and 4427 deletions

View File

@@ -0,0 +1,57 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Internal;
internal sealed class DotNetAnalyzerOptions
{
private const string DefaultConfigFileName = "dotnet-il.config.json";
[JsonPropertyName("emitDependencyEdges")]
public bool EmitDependencyEdges { get; init; } = false;
[JsonPropertyName("includeEntrypoints")]
public bool IncludeEntrypoints { get; init; } = false;
[JsonPropertyName("runtimeEvidencePath")]
public string? RuntimeEvidencePath { get; init; }
[JsonPropertyName("runtimeEvidenceConfidence")]
public string? RuntimeEvidenceConfidence { get; init; }
public static DotNetAnalyzerOptions Load(LanguageAnalyzerContext context)
{
ArgumentNullException.ThrowIfNull(context);
var path = Path.Combine(context.RootPath, DefaultConfigFileName);
if (!File.Exists(path))
{
return new DotNetAnalyzerOptions();
}
try
{
var json = File.ReadAllText(path);
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
ReadCommentHandling = JsonCommentHandling.Skip,
AllowTrailingCommas = true
};
return JsonSerializer.Deserialize<DotNetAnalyzerOptions>(json, options) ?? new DotNetAnalyzerOptions();
}
catch (IOException)
{
return new DotNetAnalyzerOptions();
}
catch (JsonException)
{
return new DotNetAnalyzerOptions();
}
catch (UnauthorizedAccessException)
{
return new DotNetAnalyzerOptions();
}
}
}

View File

@@ -0,0 +1,7 @@
namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Internal;
internal sealed record DotNetDependencyEdge(
string Target,
string Reason,
string Confidence,
string Source);

View File

@@ -0,0 +1,110 @@
using System.Text.Json;
namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Internal;
internal static class DotNetRuntimeEvidenceLoader
{
public static IReadOnlyDictionary<string, IReadOnlyList<DotNetDependencyEdge>> Load(
LanguageAnalyzerContext context,
DotNetAnalyzerOptions options,
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(options);
if (string.IsNullOrWhiteSpace(options.RuntimeEvidencePath))
{
return new Dictionary<string, IReadOnlyList<DotNetDependencyEdge>>(StringComparer.OrdinalIgnoreCase);
}
var absolute = context.ResolvePath(options.RuntimeEvidencePath);
if (!File.Exists(absolute))
{
return new Dictionary<string, IReadOnlyList<DotNetDependencyEdge>>(StringComparer.OrdinalIgnoreCase);
}
var edges = new Dictionary<string, List<DotNetDependencyEdge>>(StringComparer.OrdinalIgnoreCase);
var confidence = string.IsNullOrWhiteSpace(options.RuntimeEvidenceConfidence) ? "medium" : options.RuntimeEvidenceConfidence!.Trim();
foreach (var line in File.ReadLines(absolute))
{
cancellationToken.ThrowIfCancellationRequested();
if (string.IsNullOrWhiteSpace(line))
{
continue;
}
try
{
using var document = JsonDocument.Parse(line);
var root = document.RootElement;
if (!root.TryGetProperty("package", out var packageElement) || packageElement.ValueKind != JsonValueKind.String)
{
continue;
}
var packageId = packageElement.GetString();
if (string.IsNullOrWhiteSpace(packageId))
{
continue;
}
if (!root.TryGetProperty("target", out var targetElement) || targetElement.ValueKind != JsonValueKind.String)
{
continue;
}
var target = targetElement.GetString();
if (string.IsNullOrWhiteSpace(target))
{
continue;
}
var reason = root.TryGetProperty("reason", out var reasonElement) && reasonElement.ValueKind == JsonValueKind.String
? reasonElement.GetString()
: "runtime";
var conf = root.TryGetProperty("confidence", out var confidenceElement) && confidenceElement.ValueKind == JsonValueKind.String
? confidenceElement.GetString()
: confidence;
var source = root.TryGetProperty("source", out var sourceElement) && sourceElement.ValueKind == JsonValueKind.String
? sourceElement.GetString()
: "runtime-evidence";
var edge = new DotNetDependencyEdge(
Target: target!.Trim(),
Reason: string.IsNullOrWhiteSpace(reason) ? "runtime" : reason!.Trim(),
Confidence: string.IsNullOrWhiteSpace(conf) ? confidence : conf!.Trim(),
Source: string.IsNullOrWhiteSpace(source) ? "runtime-evidence" : source!.Trim());
if (!edges.TryGetValue(packageId.Trim().ToLowerInvariant(), out var list))
{
list = new List<DotNetDependencyEdge>();
edges[packageId.Trim().ToLowerInvariant()] = list;
}
list.Add(edge);
}
catch (JsonException)
{
continue;
}
catch (IOException)
{
continue;
}
catch (UnauthorizedAccessException)
{
continue;
}
}
return edges.ToDictionary(
kvp => kvp.Key,
kvp => (IReadOnlyList<DotNetDependencyEdge>)kvp.Value.OrderBy(edge => edge.Target, StringComparer.OrdinalIgnoreCase).ToArray(),
StringComparer.OrdinalIgnoreCase);
}
}