Skip to content

Introduce a fhirpath debug tracer #3210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from

Conversation

mmsmits
Copy link
Member

@mmsmits mmsmits commented Jul 9, 2025

Description

Introduce a capability to inject a debug trace into the fhirpath evaluation.
This will be used by systems that want to trace execution and debug what happened at each stage.
(such as in the fhirpath-lab)

Related issues

Closes|Fixes|Resolves [issue #].

Testing

There is specific unit testing to verify the captuing of the trace informtion

FirelyTeam Checklist

  • Update the title of the PR to be succinct and less than 50 characters
  • Mark the PR with the label breaking change when this PR introduces breaking changes

brianpos added 3 commits June 24, 2025 21:16
…ant (that's the base class of identifier)

Permits being able to differentiate in the expression tree between them.
only has minor impact on expression compilation, and no effect on runtime if no debugger injected.
@mmsmits mmsmits requested review from brianpos and Copilot July 17, 2025 08:11
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request introduces a FhirPath debugger feature that enables tracing of expression evaluation. The changes implement a debug tracing system that captures execution context and results for each expression during FhirPath evaluation.

  • Adds a new DebugTracer class with delegate-based tracing functionality
  • Integrates debug tracing into the expression evaluation visitor
  • Replaces ConstantExpression with IdentifierExpression for better semantic representation of identifiers

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/Hl7.Fhir.Base/FhirPath/DebugTracer.cs New debug tracer implementation with trace delegate and output formatting
src/Hl7.Fhir.Base/FhirPath/Expressions/EvaluatorVisitor.cs Integration of debug tracing wrapper and constructor parameter
src/Hl7.Fhir.Base/FhirPath/Expressions/Closure.cs Adds Variables() method to expose internal named values
src/Hl7.Fhir.Base/FhirPath/Parser/Grammar.cs Changes identifier parsing to use IdentifierExpression instead of ConstantExpression
src/Hl7.Fhir.Base/FhirPath/Expressions/ExpressionNode.cs Updates ChildExpression constructors to use IdentifierExpression
src/Hl7.FhirPath.Tests/Tests/FhirPathGrammarTest.cs Updates test expectation to use IdentifierExpression

Comment on lines 45 to 65
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},constant");
exprName = "constant";
}
else if (expr is ChildExpression child)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{child.ChildName}");
exprName = child.ChildName;
}
else if (expr is IndexerExpression indexer)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},[]");
exprName = "[]";
}
else if (expr is UnaryExpression ue)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{ue.Op}");
exprName = ue.Op;
}
else if (expr is BinaryExpression be)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{be.Op}");
Copy link
Preview

Copilot AI Jul 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The trace output format is inconsistent. Some lines use comma-separated values while others use descriptive text. Consider standardizing the format.

Suggested change
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},constant");
exprName = "constant";
}
else if (expr is ChildExpression child)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{child.ChildName}");
exprName = child.ChildName;
}
else if (expr is IndexerExpression indexer)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},[]");
exprName = "[]";
}
else if (expr is UnaryExpression ue)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{ue.Op}");
exprName = ue.Op;
}
else if (expr is BinaryExpression be)
{
System.Diagnostics.Trace.WriteLine($"{expr.Location.LineNumber},{expr.Location.LinePosition},{be.Op}");
System.Diagnostics.Trace.WriteLine($"Line: {expr.Location.LineNumber}, Position: {expr.Location.LinePosition}, Type: constant");
exprName = "constant";
}
else if (expr is ChildExpression child)
{
System.Diagnostics.Trace.WriteLine($"Line: {expr.Location.LineNumber}, Position: {expr.Location.LinePosition}, Type: Child, Name: {child.ChildName}");
exprName = child.ChildName;
}
else if (expr is IndexerExpression indexer)
{
System.Diagnostics.Trace.WriteLine($"Line: {expr.Location.LineNumber}, Position: {expr.Location.LinePosition}, Type: Indexer, Symbol: []");
exprName = "[]";
}
else if (expr is UnaryExpression ue)
{
System.Diagnostics.Trace.WriteLine($"Line: {expr.Location.LineNumber}, Position: {expr.Location.LinePosition}, Type: Unary, Operator: {ue.Op}");
exprName = ue.Op;
}
else if (expr is BinaryExpression be)
{
System.Diagnostics.Trace.WriteLine($"Line: {expr.Location.LineNumber}, Position: {expr.Location.LinePosition}, Type: Binary, Operator: {be.Op}");

Copilot uses AI. Check for mistakes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was intentionally keeping the descriptions brief.
And are consistent with how I'm displaying them in the fhirpath-lab, but not fussed if we adopted this.

brianpos and others added 3 commits July 18, 2025 10:54
Only inject the debugger break when in debug mode.
This code should never be hit, so excluding the break is good. Intended to wake the developer if it ever hits here, as that means a new Expression type has been added that doesn't derived from one of the existing ones.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@brianpos brianpos changed the title Feature/bp fhirpath debugger Introduce a fhirpath debug tracer Jul 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants