-
Notifications
You must be signed in to change notification settings - Fork 0
Debugging and Analysis
RuleScript exposes strict analysis, best-effort editor analysis, formatting, navigation, runtime events, breakpoints, and debug sessions. In v1.10.0 the same debug model can also create Host Trigger runtimes.
Analyze parses complete source and returns symbols without executing it. Syntax errors throw SyntaxException; semantic errors are returned in Diagnostics.
var engine = new RuleScriptEngine();
RuleScriptAnalysisResult symbols = engine.Analyze(script);
foreach (var function in symbols.Functions)
{
Console.WriteLine($"{function.Kind}: {function.Signature}");
}
foreach (var diagnostic in symbols.Diagnostics)
{
Console.WriteLine($"{diagnostic.Severity} {diagnostic.Code}: {diagnostic.Message}");
}For cursor-aware completion, call Analyze(script, line, column) and read VisibleVariables or VisibleVariableNames. Lines and columns are 1-based.
TryAnalyze does not throw for recoverable syntax errors. It returns partial symbols and diagnostics, which makes it suitable for text being edited.
RuleScriptAnalysisAttempt attempt = engine.TryAnalyze(editorText, cursorLine, cursorColumn);
foreach (var diagnostic in attempt.Diagnostics)
{
Console.WriteLine(
$"{diagnostic.Severity} {diagnostic.Code} " +
$"at {diagnostic.Line}:{diagnostic.Column}: {diagnostic.Message}");
}
IReadOnlyList<RuleScriptVariableSymbol> completionVariables =
attempt.Symbols.VisibleVariables;Success is false when at least one diagnostic has Error severity. Warnings are allowed.
Use SetKnownVariable when a value will be supplied by the host at execution time. This suppresses undefined-variable warnings and lets the analyzer check its type.
engine.SetKnownVariable("Distance", RuleScriptValueType.Number);
engine.SetKnownVariable("CustomerName", RuleScriptValueType.String);
RuleScriptAnalysisAttempt analysis = engine.TryAnalyze("""
var label = CustomerName + ": " + ToString(Distance);
var alert = Distance > 500;
""");Known variables configure analysis only; the runtime context still needs actual values.
Use RuleScriptAnalysisResult.Functions as the primary function metadata source. It includes user, imported, host, and built-in functions.
foreach (var symbol in symbols.Functions)
{
Console.WriteLine(symbol.Kind);
Console.WriteLine(symbol.Signature);
Console.WriteLine(symbol.Documentation);
}Host Trigger functions also appear in HostTriggers:
foreach (var trigger in symbols.HostTriggers)
{
Console.WriteLine(trigger.HostTriggerMetadata?.Name);
Console.WriteLine(trigger.Signature);
}using RuleScript.Core.Formatting;
var formatted = RuleScriptFormatter.Format(source);RuleScriptFormatter.Format(source) normalizes valid source with four-space indentation, canonical spacing, normalized block layout, and preserved comments/directives. It also normalizes @HostTrigger(...) function and @HostTrigger(...) export function into the canonical multi-line attribute form.
RuleScriptLanguageService.GetRegions(source) returns named, nested source ranges for #region and #endregion editor folding.
RuleScriptLanguageService.GetFunctionDocumentation(source, functionName) returns the normalized /// documentation attached to a user function.
Use RuleScriptLanguageService to query one-based source positions:
var definition = RuleScriptLanguageService.GetDefinition(engine, source, line: 4, column: 1);
var references = RuleScriptLanguageService.FindReferences(engine, source, line: 4, column: 1);GetDefinition returns RuleScriptDefinitionInfo?. FindReferences returns IReadOnlyList<RuleScriptReferenceInfo>. Both can resolve local variables, parameters, functions, imported functions, registered host functions, and built-ins.
Editor integrations can parse and analyze once, then reuse the result:
var document = RuleScriptLanguageService.AnalyzeDocument(engine, source);
var definition = RuleScriptLanguageService.GetDefinition(document, line: 4, column: 1);
var references = RuleScriptLanguageService.FindReferences(document, line: 4, column: 1);Use RuleScriptAnalysisCache when an editor keeps multiple open documents:
var cache = new RuleScriptAnalysisCache(engine);
var document = cache.GetOrAnalyze("main.rules", source);The cache replaces a document when its source text changes.
var engine = new RuleScriptEngine
{
WorkingDirectory = @"C:\rules"
};
engine.AddBreakpoint("main.rules", 3);
engine.AddBreakpoint("main.rules", 5, "score > 80");
var session = new RuleScriptDebugSession(engine);
Task<RuntimeContext> runTask = session.RunFileAsync("main.rules");
RuleScriptRuntimeEvent pause = await session.WaitForPauseAsync();
Console.WriteLine($"Paused at {pause.Location.File}:{pause.Location.Line}");
session.StepOver();
pause = await session.WaitForPauseAsync();
session.Continue();
RuntimeContext context = await runTask;At a pause point, CurrentSnapshot exposes source location, globals, current function locals, and call stack.
var engine = new RuleScriptEngine
{
WorkingDirectory = @"C:\rules",
ExecutionTimeoutEnabled = false
};
engine.AddBreakpoint("main.rules", 12);
var session = new RuleScriptDebugSession(engine);
var runtime = session.CreateRuntimeFromFile("main.rules");
var running = runtime.StartAsync();
await runtime.TriggerAsync("LotArrived", ["LOT-001"]);
var pause = await session.WaitForPauseAsync();
Console.WriteLine(pause.Location.Line);
session.Continue();
await runtime.StopAsync();
await running;Debug-created runtimes preserve breakpoint, stepping, pause, continue, runtime-event inspection, and snapshot behavior while the runtime is executing.
var engine = new RuleScriptEngine
{
ExecutionTimeout = TimeSpan.FromSeconds(10),
ExecutionTimeoutEnabled = true,
MaxCallDepth = 50,
CallDepthLimitEnabled = true,
MaxExecutedStatements = 100_000,
StatementExecutionLimitEnabled = true,
MaxLoopIterations = 10_000,
LoopIterationLimitEnabled = true
};| Limit | Scope | Default |
|---|---|---|
ExecutionTimeout |
Elapsed time for one run, checked at statement boundaries. | 30 seconds |
MaxCallDepth |
Active user function calls. | 100 |
MaxExecutedStatements |
Total statements across the complete run. | 1,000,000 |
MaxLoopIterations |
Iterations of each individual while or foreach. |
Engine default |
Long-running Host Trigger runtimes commonly disable ExecutionTimeoutEnabled; the host should still use cancellation and StopAsync.
RuleScriptDiagnostic provides message, severity, code, token text, source file, source location, and optional half-open range. Use codes for program logic and messages for display.
Common diagnostics include syntax errors, undefined variables, undefined functions, type mismatches, duplicate declarations, invalid assignments, invalid property/index access, parallel-task errors, duplicate overload signatures, no matching overload, ambiguous overloads, and invalid return paths.