up
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Internal;
|
||||
|
||||
internal sealed record DotNetDependencyEdge(
|
||||
string Target,
|
||||
string Reason,
|
||||
string Confidence,
|
||||
string Source);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user