prep docs and service updates
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user