Add call graph fixtures for various languages and scenarios
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Reachability Corpus Validation / validate-corpus (push) Has been cancelled
Reachability Corpus Validation / validate-ground-truths (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Reachability Corpus Validation / determinism-check (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Reachability Corpus Validation / validate-corpus (push) Has been cancelled
Reachability Corpus Validation / validate-ground-truths (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Reachability Corpus Validation / determinism-check (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
- Introduced `all-edge-reasons.json` to test edge resolution reasons in .NET. - Added `all-visibility-levels.json` to validate method visibility levels in .NET. - Created `dotnet-aspnetcore-minimal.json` for a minimal ASP.NET Core application. - Included `go-gin-api.json` for a Go Gin API application structure. - Added `java-spring-boot.json` for the Spring PetClinic application in Java. - Introduced `legacy-no-schema.json` for legacy application structure without schema. - Created `node-express-api.json` for an Express.js API application structure.
This commit is contained in:
@@ -173,6 +173,14 @@ internal sealed class DotNetCallgraphBuilder
|
||||
var isVirtual = (methodDef.Attributes & MethodAttributes.Virtual) != 0;
|
||||
var isGeneric = methodDef.GetGenericParameters().Count > 0;
|
||||
|
||||
// Extract visibility from MethodAttributes
|
||||
var visibility = ExtractVisibility(methodDef.Attributes);
|
||||
|
||||
// Determine if this method is an entrypoint candidate
|
||||
var isTypePublic = (typeDef.Attributes & TypeAttributes.Public) != 0 ||
|
||||
(typeDef.Attributes & TypeAttributes.NestedPublic) != 0;
|
||||
var isEntrypointCandidate = isPublic && isTypePublic && !methodName.StartsWith("<");
|
||||
|
||||
var node = new DotNetMethodNode(
|
||||
MethodId: methodId,
|
||||
AssemblyName: assemblyName,
|
||||
@@ -186,7 +194,9 @@ internal sealed class DotNetCallgraphBuilder
|
||||
IsStatic: isStatic,
|
||||
IsPublic: isPublic,
|
||||
IsVirtual: isVirtual,
|
||||
IsGeneric: isGeneric);
|
||||
IsGeneric: isGeneric,
|
||||
Visibility: visibility,
|
||||
IsEntrypointCandidate: isEntrypointCandidate);
|
||||
|
||||
_methods.TryAdd(methodId, node);
|
||||
|
||||
@@ -254,6 +264,7 @@ internal sealed class DotNetCallgraphBuilder
|
||||
!methodName.StartsWith("get_") && !methodName.StartsWith("set_") &&
|
||||
methodName != ".ctor")
|
||||
{
|
||||
var (routeTemplate, httpMethod) = ExtractRouteInfo(metadata, methodDef.GetCustomAttributes());
|
||||
var rootId = DotNetGraphIdentifiers.ComputeRootId(DotNetRootPhase.Runtime, rootOrder++, methodId);
|
||||
_roots.Add(new DotNetSyntheticRoot(
|
||||
RootId: rootId,
|
||||
@@ -262,14 +273,29 @@ internal sealed class DotNetCallgraphBuilder
|
||||
Source: "ControllerAction",
|
||||
AssemblyPath: assemblyPath,
|
||||
Phase: DotNetRootPhase.Runtime,
|
||||
Order: rootOrder - 1));
|
||||
Order: rootOrder - 1,
|
||||
RouteTemplate: routeTemplate,
|
||||
HttpMethod: httpMethod,
|
||||
Framework: DotNetEntrypointFramework.AspNetCore));
|
||||
}
|
||||
|
||||
// Test methods (xUnit, NUnit, MSTest)
|
||||
var testFramework = DotNetEntrypointFramework.Unknown;
|
||||
if (HasAttribute(metadata, methodDef.GetCustomAttributes(), "Xunit.FactAttribute") ||
|
||||
HasAttribute(metadata, methodDef.GetCustomAttributes(), "Xunit.TheoryAttribute") ||
|
||||
HasAttribute(metadata, methodDef.GetCustomAttributes(), "NUnit.Framework.TestAttribute") ||
|
||||
HasAttribute(metadata, methodDef.GetCustomAttributes(), "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute"))
|
||||
HasAttribute(metadata, methodDef.GetCustomAttributes(), "Xunit.TheoryAttribute"))
|
||||
{
|
||||
testFramework = DotNetEntrypointFramework.XUnit;
|
||||
}
|
||||
else if (HasAttribute(metadata, methodDef.GetCustomAttributes(), "NUnit.Framework.TestAttribute"))
|
||||
{
|
||||
testFramework = DotNetEntrypointFramework.NUnit;
|
||||
}
|
||||
else if (HasAttribute(metadata, methodDef.GetCustomAttributes(), "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute"))
|
||||
{
|
||||
testFramework = DotNetEntrypointFramework.MSTest;
|
||||
}
|
||||
|
||||
if (testFramework != DotNetEntrypointFramework.Unknown)
|
||||
{
|
||||
var rootId = DotNetGraphIdentifiers.ComputeRootId(DotNetRootPhase.Runtime, rootOrder++, methodId);
|
||||
_roots.Add(new DotNetSyntheticRoot(
|
||||
@@ -279,7 +305,8 @@ internal sealed class DotNetCallgraphBuilder
|
||||
Source: "TestMethod",
|
||||
AssemblyPath: assemblyPath,
|
||||
Phase: DotNetRootPhase.Runtime,
|
||||
Order: rootOrder - 1));
|
||||
Order: rootOrder - 1,
|
||||
Framework: testFramework));
|
||||
}
|
||||
|
||||
// Azure Functions
|
||||
@@ -294,7 +321,8 @@ internal sealed class DotNetCallgraphBuilder
|
||||
Source: "AzureFunction",
|
||||
AssemblyPath: assemblyPath,
|
||||
Phase: DotNetRootPhase.Runtime,
|
||||
Order: rootOrder - 1));
|
||||
Order: rootOrder - 1,
|
||||
Framework: DotNetEntrypointFramework.AzureFunctions));
|
||||
}
|
||||
|
||||
// AWS Lambda
|
||||
@@ -308,10 +336,120 @@ internal sealed class DotNetCallgraphBuilder
|
||||
Source: "LambdaHandler",
|
||||
AssemblyPath: assemblyPath,
|
||||
Phase: DotNetRootPhase.Runtime,
|
||||
Order: rootOrder - 1));
|
||||
Order: rootOrder - 1,
|
||||
Framework: DotNetEntrypointFramework.AwsLambda));
|
||||
}
|
||||
}
|
||||
|
||||
private static (string? RouteTemplate, string? HttpMethod) ExtractRouteInfo(
|
||||
MetadataReader metadata,
|
||||
CustomAttributeHandleCollection attributes)
|
||||
{
|
||||
string? routeTemplate = null;
|
||||
string? httpMethod = null;
|
||||
|
||||
foreach (var attrHandle in attributes)
|
||||
{
|
||||
var attr = metadata.GetCustomAttribute(attrHandle);
|
||||
var ctorHandle = attr.Constructor;
|
||||
|
||||
string? typeName = null;
|
||||
switch (ctorHandle.Kind)
|
||||
{
|
||||
case HandleKind.MemberReference:
|
||||
var memberRef = metadata.GetMemberReference((MemberReferenceHandle)ctorHandle);
|
||||
if (memberRef.Parent.Kind == HandleKind.TypeReference)
|
||||
{
|
||||
var typeRef = metadata.GetTypeReference((TypeReferenceHandle)memberRef.Parent);
|
||||
typeName = GetTypeRefName(metadata, typeRef);
|
||||
}
|
||||
break;
|
||||
case HandleKind.MethodDefinition:
|
||||
var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)ctorHandle);
|
||||
var declaringType = metadata.GetTypeDefinition(methodDef.GetDeclaringType());
|
||||
typeName = GetFullTypeName(metadata, declaringType);
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeName is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extract route template from [Route] attribute
|
||||
if (typeName.Contains("RouteAttribute"))
|
||||
{
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
|
||||
// Extract HTTP method and optional route from Http*Attribute
|
||||
if (typeName.Contains("HttpGetAttribute"))
|
||||
{
|
||||
httpMethod = "GET";
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
else if (typeName.Contains("HttpPostAttribute"))
|
||||
{
|
||||
httpMethod = "POST";
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
else if (typeName.Contains("HttpPutAttribute"))
|
||||
{
|
||||
httpMethod = "PUT";
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
else if (typeName.Contains("HttpDeleteAttribute"))
|
||||
{
|
||||
httpMethod = "DELETE";
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
else if (typeName.Contains("HttpPatchAttribute"))
|
||||
{
|
||||
httpMethod = "PATCH";
|
||||
routeTemplate ??= TryExtractStringArgument(metadata, attr);
|
||||
}
|
||||
}
|
||||
|
||||
return (routeTemplate, httpMethod);
|
||||
}
|
||||
|
||||
private static string? TryExtractStringArgument(MetadataReader metadata, CustomAttribute attr)
|
||||
{
|
||||
// Simplified extraction - read first string argument from attribute blob
|
||||
// Full implementation would properly parse the custom attribute blob
|
||||
try
|
||||
{
|
||||
var value = attr.DecodeValue(new SimpleAttributeProvider());
|
||||
if (value.FixedArguments.Length > 0 &&
|
||||
value.FixedArguments[0].Value is string strValue &&
|
||||
!string.IsNullOrEmpty(strValue))
|
||||
{
|
||||
return strValue;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Attribute decoding failed - not critical
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple attribute type provider for decoding custom attributes.
|
||||
/// </summary>
|
||||
private sealed class SimpleAttributeProvider : ICustomAttributeTypeProvider<object?>
|
||||
{
|
||||
public object? GetPrimitiveType(PrimitiveTypeCode typeCode) => null;
|
||||
public object? GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => null;
|
||||
public object? GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => null;
|
||||
public object? GetSZArrayType(object? elementType) => null;
|
||||
public object? GetSystemType() => typeof(Type);
|
||||
public object? GetTypeFromSerializedName(string name) => Type.GetType(name);
|
||||
public PrimitiveTypeCode GetUnderlyingEnumType(object? type) => PrimitiveTypeCode.Int32;
|
||||
public bool IsSystemType(object? type) => type is Type;
|
||||
}
|
||||
|
||||
private void ExtractCallEdgesFromType(
|
||||
MetadataReader metadata,
|
||||
TypeDefinition typeDef,
|
||||
@@ -390,15 +528,15 @@ internal sealed class DotNetCallgraphBuilder
|
||||
var token = BitConverter.ToInt32(ilBytes, offset);
|
||||
offset += 4;
|
||||
|
||||
var edgeType = opcode switch
|
||||
var (edgeType, edgeReason) = opcode switch
|
||||
{
|
||||
0x28 => DotNetEdgeType.Call,
|
||||
0x6F => DotNetEdgeType.CallVirt,
|
||||
0x73 => DotNetEdgeType.NewObj,
|
||||
_ => DotNetEdgeType.Call,
|
||||
0x28 => (DotNetEdgeType.Call, DotNetEdgeReason.DirectCall),
|
||||
0x6F => (DotNetEdgeType.CallVirt, DotNetEdgeReason.VirtualCall),
|
||||
0x73 => (DotNetEdgeType.NewObj, DotNetEdgeReason.NewObj),
|
||||
_ => (DotNetEdgeType.Call, DotNetEdgeReason.DirectCall),
|
||||
};
|
||||
|
||||
AddCallEdge(metadata, callerId, token, ilOffset, edgeType, assemblyName, assemblyPath);
|
||||
AddCallEdge(metadata, callerId, token, ilOffset, edgeType, edgeReason, assemblyName, assemblyPath);
|
||||
break;
|
||||
}
|
||||
case 0xFE06: // ldftn (0xFE 0x06)
|
||||
@@ -413,7 +551,7 @@ internal sealed class DotNetCallgraphBuilder
|
||||
offset += 4;
|
||||
|
||||
var edgeType = opcode == 0xFE06 ? DotNetEdgeType.LdFtn : DotNetEdgeType.LdVirtFtn;
|
||||
AddCallEdge(metadata, callerId, token, ilOffset, edgeType, assemblyName, assemblyPath);
|
||||
AddCallEdge(metadata, callerId, token, ilOffset, edgeType, DotNetEdgeReason.DelegateCreate, assemblyName, assemblyPath);
|
||||
break;
|
||||
}
|
||||
case 0x29: // calli
|
||||
@@ -436,6 +574,7 @@ internal sealed class DotNetCallgraphBuilder
|
||||
CalleePurl: null,
|
||||
CalleeMethodDigest: null,
|
||||
EdgeType: DotNetEdgeType.CallI,
|
||||
EdgeReason: DotNetEdgeReason.IndirectCall,
|
||||
ILOffset: ilOffset,
|
||||
IsResolved: false,
|
||||
Confidence: 0.2));
|
||||
@@ -470,6 +609,7 @@ internal sealed class DotNetCallgraphBuilder
|
||||
int token,
|
||||
int ilOffset,
|
||||
DotNetEdgeType edgeType,
|
||||
DotNetEdgeReason edgeReason,
|
||||
string assemblyName,
|
||||
string assemblyPath)
|
||||
{
|
||||
@@ -517,8 +657,8 @@ internal sealed class DotNetCallgraphBuilder
|
||||
case HandleKind.MethodSpecification:
|
||||
{
|
||||
var methodSpec = metadata.GetMethodSpecification((MethodSpecificationHandle)handle);
|
||||
// Recursively resolve the generic method
|
||||
AddCallEdge(metadata, callerId, MetadataTokens.GetToken(methodSpec.Method), ilOffset, edgeType, assemblyName, assemblyPath);
|
||||
// Recursively resolve the generic method - use GenericInstantiation reason
|
||||
AddCallEdge(metadata, callerId, MetadataTokens.GetToken(methodSpec.Method), ilOffset, edgeType, DotNetEdgeReason.GenericInstantiation, assemblyName, assemblyPath);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@@ -549,6 +689,7 @@ internal sealed class DotNetCallgraphBuilder
|
||||
CalleePurl: calleePurl,
|
||||
CalleeMethodDigest: null,
|
||||
EdgeType: edgeType,
|
||||
EdgeReason: edgeReason,
|
||||
ILOffset: ilOffset,
|
||||
IsResolved: isResolved,
|
||||
Confidence: isResolved ? 1.0 : 0.7));
|
||||
@@ -788,4 +929,19 @@ internal sealed class DotNetCallgraphBuilder
|
||||
_ => 1, // default for unrecognized
|
||||
};
|
||||
}
|
||||
|
||||
private static DotNetVisibility ExtractVisibility(MethodAttributes attributes)
|
||||
{
|
||||
var accessMask = attributes & MethodAttributes.MemberAccessMask;
|
||||
return accessMask switch
|
||||
{
|
||||
MethodAttributes.Public => DotNetVisibility.Public,
|
||||
MethodAttributes.Private => DotNetVisibility.Private,
|
||||
MethodAttributes.Family => DotNetVisibility.Protected,
|
||||
MethodAttributes.Assembly => DotNetVisibility.Internal,
|
||||
MethodAttributes.FamORAssem => DotNetVisibility.ProtectedInternal,
|
||||
MethodAttributes.FamANDAssem => DotNetVisibility.PrivateProtected,
|
||||
_ => DotNetVisibility.Private
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ public sealed record DotNetReachabilityGraph(
|
||||
/// <param name="IsPublic">Whether the method is public.</param>
|
||||
/// <param name="IsVirtual">Whether the method is virtual.</param>
|
||||
/// <param name="IsGeneric">Whether the method has generic parameters.</param>
|
||||
/// <param name="Visibility">Access visibility (public, private, protected, internal, etc.).</param>
|
||||
/// <param name="IsEntrypointCandidate">Whether this method could be an entrypoint (public, controller action, etc.).</param>
|
||||
public sealed record DotNetMethodNode(
|
||||
string MethodId,
|
||||
string AssemblyName,
|
||||
@@ -45,7 +47,33 @@ public sealed record DotNetMethodNode(
|
||||
bool IsStatic,
|
||||
bool IsPublic,
|
||||
bool IsVirtual,
|
||||
bool IsGeneric);
|
||||
bool IsGeneric,
|
||||
DotNetVisibility Visibility,
|
||||
bool IsEntrypointCandidate);
|
||||
|
||||
/// <summary>
|
||||
/// Access visibility levels for .NET methods.
|
||||
/// </summary>
|
||||
public enum DotNetVisibility
|
||||
{
|
||||
/// <summary>Accessible from anywhere.</summary>
|
||||
Public,
|
||||
|
||||
/// <summary>Accessible only within the same type.</summary>
|
||||
Private,
|
||||
|
||||
/// <summary>Accessible within the same type or derived types.</summary>
|
||||
Protected,
|
||||
|
||||
/// <summary>Accessible within the same assembly.</summary>
|
||||
Internal,
|
||||
|
||||
/// <summary>Accessible within the same assembly or derived types.</summary>
|
||||
ProtectedInternal,
|
||||
|
||||
/// <summary>Accessible only within derived types in the same assembly.</summary>
|
||||
PrivateProtected
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A call edge in the .NET call graph.
|
||||
@@ -56,6 +84,7 @@ public sealed record DotNetMethodNode(
|
||||
/// <param name="CalleePurl">PURL of the callee if resolvable.</param>
|
||||
/// <param name="CalleeMethodDigest">Method digest of the callee.</param>
|
||||
/// <param name="EdgeType">Type of edge (call instruction type).</param>
|
||||
/// <param name="EdgeReason">Semantic reason for the edge (DirectCall, VirtualCall, etc.).</param>
|
||||
/// <param name="ILOffset">IL offset where call occurs.</param>
|
||||
/// <param name="IsResolved">Whether the callee was successfully resolved.</param>
|
||||
/// <param name="Confidence">Confidence level (1.0 for resolved, lower for heuristic).</param>
|
||||
@@ -66,6 +95,7 @@ public sealed record DotNetCallEdge(
|
||||
string? CalleePurl,
|
||||
string? CalleeMethodDigest,
|
||||
DotNetEdgeType EdgeType,
|
||||
DotNetEdgeReason EdgeReason,
|
||||
int ILOffset,
|
||||
bool IsResolved,
|
||||
double Confidence);
|
||||
@@ -103,6 +133,52 @@ public enum DotNetEdgeType
|
||||
Dynamic,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Semantic reason for why a .NET edge exists.
|
||||
/// Maps to the schema's EdgeReason enum for explainability.
|
||||
/// </summary>
|
||||
public enum DotNetEdgeReason
|
||||
{
|
||||
/// <summary>Direct method call (call opcode).</summary>
|
||||
DirectCall,
|
||||
|
||||
/// <summary>Virtual/interface dispatch (callvirt opcode).</summary>
|
||||
VirtualCall,
|
||||
|
||||
/// <summary>Reflection-based invocation (Type.GetMethod, etc.).</summary>
|
||||
ReflectionString,
|
||||
|
||||
/// <summary>Dependency injection binding.</summary>
|
||||
DiBinding,
|
||||
|
||||
/// <summary>Dynamic import or late binding.</summary>
|
||||
DynamicImport,
|
||||
|
||||
/// <summary>Constructor/object instantiation (newobj opcode).</summary>
|
||||
NewObj,
|
||||
|
||||
/// <summary>Delegate/function pointer creation (ldftn, ldvirtftn).</summary>
|
||||
DelegateCreate,
|
||||
|
||||
/// <summary>Async/await continuation.</summary>
|
||||
AsyncContinuation,
|
||||
|
||||
/// <summary>Event handler subscription.</summary>
|
||||
EventHandler,
|
||||
|
||||
/// <summary>Generic type instantiation.</summary>
|
||||
GenericInstantiation,
|
||||
|
||||
/// <summary>Native interop (P/Invoke).</summary>
|
||||
NativeInterop,
|
||||
|
||||
/// <summary>Indirect call through function pointer (calli).</summary>
|
||||
IndirectCall,
|
||||
|
||||
/// <summary>Reason could not be determined.</summary>
|
||||
Unknown
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A synthetic root in the .NET call graph.
|
||||
/// </summary>
|
||||
@@ -114,6 +190,9 @@ public enum DotNetEdgeType
|
||||
/// <param name="Phase">Execution phase.</param>
|
||||
/// <param name="Order">Order within the phase.</param>
|
||||
/// <param name="IsResolved">Whether the target was successfully resolved.</param>
|
||||
/// <param name="RouteTemplate">HTTP route template if applicable (e.g., "/api/orders/{id}").</param>
|
||||
/// <param name="HttpMethod">HTTP method if applicable (GET, POST, etc.).</param>
|
||||
/// <param name="Framework">Framework exposing this entrypoint.</param>
|
||||
public sealed record DotNetSyntheticRoot(
|
||||
string RootId,
|
||||
string TargetId,
|
||||
@@ -122,7 +201,43 @@ public sealed record DotNetSyntheticRoot(
|
||||
string AssemblyPath,
|
||||
DotNetRootPhase Phase,
|
||||
int Order,
|
||||
bool IsResolved = true);
|
||||
bool IsResolved = true,
|
||||
string? RouteTemplate = null,
|
||||
string? HttpMethod = null,
|
||||
DotNetEntrypointFramework Framework = DotNetEntrypointFramework.Unknown);
|
||||
|
||||
/// <summary>
|
||||
/// Frameworks that expose .NET entrypoints.
|
||||
/// </summary>
|
||||
public enum DotNetEntrypointFramework
|
||||
{
|
||||
/// <summary>Unknown framework.</summary>
|
||||
Unknown,
|
||||
|
||||
/// <summary>ASP.NET Core MVC/WebAPI.</summary>
|
||||
AspNetCore,
|
||||
|
||||
/// <summary>ASP.NET Core Minimal APIs.</summary>
|
||||
MinimalApi,
|
||||
|
||||
/// <summary>gRPC for .NET.</summary>
|
||||
Grpc,
|
||||
|
||||
/// <summary>Azure Functions.</summary>
|
||||
AzureFunctions,
|
||||
|
||||
/// <summary>AWS Lambda.</summary>
|
||||
AwsLambda,
|
||||
|
||||
/// <summary>xUnit test framework.</summary>
|
||||
XUnit,
|
||||
|
||||
/// <summary>NUnit test framework.</summary>
|
||||
NUnit,
|
||||
|
||||
/// <summary>MSTest framework.</summary>
|
||||
MSTest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execution phase for .NET synthetic roots.
|
||||
|
||||
Reference in New Issue
Block a user