prep docs and service updates
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
master
2025-11-21 06:56:36 +00:00
parent ca35db9ef4
commit d519782a8f
242 changed files with 17293 additions and 13367 deletions

View File

@@ -3,10 +3,13 @@ using StellaOps.Signals.Models;
namespace StellaOps.Signals.Parsing;
/// <summary>
/// Result produced by a callgraph parser.
/// </summary>
public sealed record CallgraphParseResult(
IReadOnlyList<CallgraphNode> Nodes,
IReadOnlyList<CallgraphEdge> Edges,
string FormatVersion);
/// <summary>
/// Result produced by a callgraph parser.
/// </summary>
public sealed record CallgraphParseResult(
IReadOnlyList<CallgraphNode> Nodes,
IReadOnlyList<CallgraphEdge> Edges,
IReadOnlyList<CallgraphRoot> Roots,
string FormatVersion,
string SchemaVersion,
IReadOnlyDictionary<string, string?>? Analyzer = null);

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Signals.Models;
namespace StellaOps.Signals.Parsing;
@@ -74,7 +74,14 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
Kind: nodeElement.TryGetProperty("kind", out var kindEl) ? kindEl.GetString() ?? "function" : "function",
Namespace: nodeElement.TryGetProperty("namespace", out var nsEl) ? nsEl.GetString() : null,
File: nodeElement.TryGetProperty("file", out var fileEl) ? fileEl.GetString() : null,
Line: nodeElement.TryGetProperty("line", out var lineEl) && lineEl.ValueKind == JsonValueKind.Number ? lineEl.GetInt32() : null));
Line: nodeElement.TryGetProperty("line", out var lineEl) && lineEl.ValueKind == JsonValueKind.Number ? lineEl.GetInt32() : null,
Purl: GetString(nodeElement, "purl"),
SymbolDigest: GetString(nodeElement, "symbol_digest", "symbolDigest"),
BuildId: GetString(nodeElement, "build_id", "buildId"),
Language: GetString(nodeElement, "language"),
Evidence: GetStringArray(nodeElement, "evidence"),
Analyzer: GetStringDictionary(nodeElement, "analyzer"),
CodeId: GetString(nodeElement, "code_id", "codeId")));
}
var edges = new List<CallgraphEdge>();
@@ -90,7 +97,15 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
}
var type = edgeElement.TryGetProperty("type", out var typeEl) ? typeEl.GetString() ?? "call" : "call";
edges.Add(new CallgraphEdge(source.Trim(), target.Trim(), type));
edges.Add(new CallgraphEdge(
source.Trim(),
target.Trim(),
type,
Purl: GetString(edgeElement, "purl"),
SymbolDigest: GetString(edgeElement, "symbol_digest", "symbolDigest"),
Candidates: GetStringArray(edgeElement, "candidates"),
Confidence: GetNullableDouble(edgeElement, "confidence"),
Evidence: GetStringArray(edgeElement, "evidence")));
}
}
@@ -98,7 +113,19 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
? versionEl.GetString()
: null;
result = new CallgraphParseResult(nodes, edges, string.IsNullOrWhiteSpace(formatVersion) ? "1.0" : formatVersion!.Trim());
var schemaVersion = root.TryGetProperty("schema_version", out var schemaEl)
? schemaEl.GetString()
: formatVersion;
var analyzer = GetStringDictionary(root, "analyzer") ?? GetStringDictionary(root, "toolchain");
result = new CallgraphParseResult(
nodes,
edges,
Array.Empty<CallgraphRoot>(),
string.IsNullOrWhiteSpace(formatVersion) ? "1.0" : formatVersion!.Trim(),
string.IsNullOrWhiteSpace(schemaVersion) ? "1.0" : schemaVersion!.Trim(),
analyzer);
return true;
}
@@ -128,7 +155,14 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
Kind: nodeElement.TryGetProperty("kind", out var kindEl) ? kindEl.GetString() ?? "function" : "function",
Namespace: nodeElement.TryGetProperty("namespace", out var nsEl) ? nsEl.GetString() : null,
File: nodeElement.TryGetProperty("file", out var fileEl) ? fileEl.GetString() : null,
Line: nodeElement.TryGetProperty("line", out var lineEl) && lineEl.ValueKind == JsonValueKind.Number ? lineEl.GetInt32() : null));
Line: nodeElement.TryGetProperty("line", out var lineEl) && lineEl.ValueKind == JsonValueKind.Number ? lineEl.GetInt32() : null,
Purl: GetString(nodeElement, "purl"),
SymbolDigest: GetString(nodeElement, "symbol_digest", "symbolDigest"),
BuildId: GetString(nodeElement, "build_id", "buildId"),
Language: GetString(nodeElement, "language"),
Evidence: GetStringArray(nodeElement, "evidence"),
Analyzer: GetStringDictionary(nodeElement, "analyzer"),
CodeId: GetString(nodeElement, "code_id", "codeId")));
}
}
@@ -155,7 +189,15 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
? typeEl.GetString() ?? "call"
: "call";
edges.Add(new CallgraphEdge(from.Trim(), to.Trim(), kind));
edges.Add(new CallgraphEdge(
from.Trim(),
to.Trim(),
kind,
Purl: GetString(edgeElement, "purl"),
SymbolDigest: GetString(edgeElement, "symbol_digest", "symbolDigest"),
Candidates: GetStringArray(edgeElement, "candidates"),
Confidence: GetNullableDouble(edgeElement, "confidence"),
Evidence: GetStringArray(edgeElement, "evidence")));
}
}
@@ -171,7 +213,7 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
foreach (var nodeId in uniqueNodeIds)
{
nodes.Add(new CallgraphNode(nodeId, nodeId, "function", null, null, null));
nodes.Add(new CallgraphNode(nodeId, nodeId, "function", null, null, null, null, null, null, null, null, null, null));
}
}
@@ -179,8 +221,105 @@ public sealed class SimpleJsonCallgraphParser : ICallgraphParser
? schemaEl.GetString()
: "1.0";
result = new CallgraphParseResult(nodes, edges, string.IsNullOrWhiteSpace(schemaVersion) ? "1.0" : schemaVersion!.Trim());
var roots = ParseRoots(root);
var analyzer = GetStringDictionary(root, "analyzer") ?? GetStringDictionary(root, "toolchain");
result = new CallgraphParseResult(
nodes,
edges,
roots,
string.IsNullOrWhiteSpace(schemaVersion) ? "1.0" : schemaVersion!.Trim(),
string.IsNullOrWhiteSpace(schemaVersion) ? "1.0" : schemaVersion!.Trim(),
analyzer);
return true;
}
private static IReadOnlyList<CallgraphRoot> ParseRoots(JsonElement root)
{
if (!root.TryGetProperty("roots", out var rootsEl) || rootsEl.ValueKind != JsonValueKind.Array)
{
return Array.Empty<CallgraphRoot>();
}
var roots = new List<CallgraphRoot>(rootsEl.GetArrayLength());
foreach (var r in rootsEl.EnumerateArray())
{
var id = GetString(r, "id");
if (string.IsNullOrWhiteSpace(id))
{
continue;
}
var phase = GetString(r, "phase") ?? "runtime";
var source = GetString(r, "source");
roots.Add(new CallgraphRoot(id.Trim(), phase.Trim(), source));
}
return roots;
}
private static string? GetString(JsonElement element, string name1, string? name2 = null)
{
if (element.TryGetProperty(name1, out var v1) && v1.ValueKind == JsonValueKind.String)
{
return v1.GetString();
}
if (!string.IsNullOrEmpty(name2) && element.TryGetProperty(name2!, out var v2) && v2.ValueKind == JsonValueKind.String)
{
return v2.GetString();
}
return null;
}
private static IReadOnlyList<string>? GetStringArray(JsonElement element, string name)
{
if (!element.TryGetProperty(name, out var arr) || arr.ValueKind != JsonValueKind.Array)
{
return null;
}
var list = new List<string>(arr.GetArrayLength());
foreach (var item in arr.EnumerateArray())
{
if (item.ValueKind == JsonValueKind.String)
{
list.Add(item.GetString()!);
}
}
return list;
}
private static IReadOnlyDictionary<string, string?>? GetStringDictionary(JsonElement element, string name)
{
if (!element.TryGetProperty(name, out var obj) || obj.ValueKind != JsonValueKind.Object)
{
return null;
}
var dict = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
foreach (var prop in obj.EnumerateObject())
{
dict[prop.Name] = prop.Value.ValueKind == JsonValueKind.String ? prop.Value.GetString() : prop.Value.ToString();
}
return dict;
}
private static double? GetNullableDouble(JsonElement element, string name)
{
if (!element.TryGetProperty(name, out var val))
{
return null;
}
return val.ValueKind switch
{
JsonValueKind.Number when val.TryGetDouble(out var d) => d,
_ => null
};
}
}