Skip to content

Conversation

@brendankowitz
Copy link
Member

@brendankowitz brendankowitz commented Oct 17, 2025

Description

This pull request introduces significant changes to how FHIR resources are represented and processed within the codebase, moving from the use of ITypedElement to PocoNode for resource elements. This update impacts a wide range of files, refactoring interfaces, implementations, and test code to align with the new model. Additionally, there are several dependency version updates and some package version downgrades.

The most important changes are:

Core Model Refactoring

  • Refactored ResourceElement and related APIs to use PocoNode instead of ITypedElement, affecting constructors, properties, and internal logic in ResourceElement, ResourceTypeExtensions, and all related usages. This change improves consistency and interoperability with the FHIR .NET library. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11]
  • Updated the IReferenceToElementResolver interface and its implementation to return PocoNode instead of ITypedElement. [1] [2] [3]
  • Changed the IModelInfoProvider.GetEvaluationContext signature to accept a resolver function returning PocoNode. [1] [2]

Dependency and Package Version Updates

  • Downgraded or updated several package versions in Directory.Packages.props, including HealthcareSharedPackageVersion, DotNetSdkPackageVersion, Azure.Identity, Microsoft.Data.SqlClient, and Newtonsoft.Json. Also, updated Hl7FhirVersion and OpenIddict packages to newer versions. [1] [2] [3] [4]
  • Added new package references, such as IdentityServer4 and updated Microsoft.EntityFrameworkCore.InMemory to a newer version. [1] [2]

Test Adjustments

  • Updated unit tests to use the new PocoNode-based APIs and adjusted mock setups and test logic accordingly. [1] [2] [3] [4] [5] [6]

Minor Logic Changes

  • Improved FHIRPath evaluation and search parameter extraction to operate on PocoNode instances, ensuring correct FHIRPath context and evaluation. [1] [2] [3]
  • Fixed logic in CreateBulkUpdateHandler to correctly extract the operation value from FHIR parameters, handling FhirString specifically.

These changes collectively modernize the resource handling pipeline and align the codebase with the latest FHIR .NET best practices.

Related issues

Addresses [issue #].

Testing

Describe how this change was tested.

FHIR Team Checklist

  • Update the title of the PR to be succinct and less than 65 characters
  • Add a milestone to the PR for the sprint that it is merged (i.e. add S47)
  • Tag the PR with the type of update: Bug, Build, Dependencies, Enhancement, New-Feature or Documentation
  • Tag the PR with Open source, Azure API for FHIR (CosmosDB or common code) or Azure Healthcare APIs (SQL or common code) to specify where this change is intended to be released.
  • Tag the PR with Schema Version backward compatible or Schema Version backward incompatible or Schema Version unchanged if this adds or updates Sql script which is/is not backward compatible with the code.
  • When changing or adding behavior, if your code modifies the system design or changes design assumptions, please create and include an ADR.
  • CI is green before merge Build Status
  • Review squash-merge requirements

Semver Change (docs)

Patch|Skip|Feature|Breaking (reason)

<PackageVersion Include="Hl7.Fhir.Specification.R4" Version="$(Hl7FhirVersion)" />
<PackageVersion Include="Hl7.Fhir.Specification.R4B" Version="$(Hl7FhirVersion)" />
<PackageVersion Include="Hl7.Fhir.Specification.R5" Version="$(Hl7FhirVersion)" />
<PackageVersion Include="IdentityServer4" Version="4.1.2" />
Copy link
Member Author

Choose a reason for hiding this comment

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

bad things happened to this merge 😞

@brendankowitz brendankowitz force-pushed the feature/firely-6-update branch from a499f9a to 41108f4 Compare October 27, 2025 23:03
ResourceWrapperOperation resourceWrapper = await BundleTestsCommonFunctions.GetResourceWrapperOperationAsync(
resource,
new BundleResourceContext(Bundle.BundleType.Batch, BundleProcessingLogic.Parallel, GetHttpVerb(i), persistedId: null, operation.Id));
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));

Check warning

Code scanning / CodeQL

Cast to same type Warning

This cast is redundant because the expression already has type Int32.

Copilot Autofix

AI about 2 months ago

To fix the issue, simply remove the redundant cast (int)i and use i directly as the argument to GetHttpVerb. This means editing the one line within the method GivenABatchOperation_WhenAppendedMultipleResourcesInParallelWaitForAllToBeAppended_ThenCompleteWithSuccess so that GetHttpVerb((int)i) becomes GetHttpVerb(i). No imports, methods, or additional definitions are required.

Suggested changeset 1
src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
--- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
+++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
@@ -92,7 +92,7 @@
             Parallel.For(0, numberOfResources, (i, task) =>
             {
                 DomainResource resource = BundleTestsCommonFunctions.GetSamplePatient(Guid.NewGuid());
-                ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));
+                ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb(i), string.Empty, operation.Id));
 
                 Task<UpsertOutcome> appendedResourceTask = operation.AppendResourceAsync(resourceWrapper, dataStore, cts.Token);
                 tasksWaitingForMergeAsync.Add(appendedResourceTask);
EOF
@@ -92,7 +92,7 @@
Parallel.For(0, numberOfResources, (i, task) =>
{
DomainResource resource = BundleTestsCommonFunctions.GetSamplePatient(Guid.NewGuid());
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb(i), string.Empty, operation.Id));

Task<UpsertOutcome> appendedResourceTask = operation.AppendResourceAsync(resourceWrapper, dataStore, cts.Token);
tasksWaitingForMergeAsync.Add(appendedResourceTask);
Copilot is powered by AI and may make mistakes. Always verify output.
ResourceWrapperOperation resourceWrapper = await BundleTestsCommonFunctions.GetResourceWrapperOperationAsync(
resource,
new BundleResourceContext(Bundle.BundleType.Batch, BundleProcessingLogic.Parallel, GetHttpVerb(i), persistedId: null, operation.Id));
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));

Check warning

Code scanning / CodeQL

Cast to same type Warning

This cast is redundant because the expression already has type Int32.

Copilot Autofix

AI about 2 months ago

The best way to fix the problem is to remove the redundant cast (int)i on line 220. Instead, pass i directly to the GetHttpVerb function. No changes are needed to any imports, method signatures, or additional code outside of removing the unnecessary cast. Only a single edit to line 220 in the file is required.

Suggested changeset 1
src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
--- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
+++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Persistence/Orchestration/BundleOrchestratorOperationTests.cs
@@ -217,7 +217,7 @@
                 else
                 {
                     DomainResource resource = BundleTestsCommonFunctions.GetSamplePatient(Guid.NewGuid());
-                    ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));
+                    ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb(i), string.Empty, operation.Id));
 
                     appendTask = operation.AppendResourceAsync(resourceWrapper, dataStore, cts.Token);
                 }
EOF
@@ -217,7 +217,7 @@
else
{
DomainResource resource = BundleTestsCommonFunctions.GetSamplePatient(Guid.NewGuid());
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb((int)i), string.Empty, operation.Id));
ResourceWrapperOperation resourceWrapper = BundleTestsCommonFunctions.GetResourceWrapperOperation(resource, new BundleResourceContext(null, BundleProcessingLogic.Parallel, GetHttpVerb(i), string.Empty, operation.Id));

appendTask = operation.AppendResourceAsync(resourceWrapper, dataStore, cts.Token);
}
Copilot is powered by AI and may make mistakes. Always verify output.
RegexOptions.Compiled);

private FhirJsonParser _parser;
private FhirJsonDeserializer _parser;

Check notice

Code scanning / CodeQL

Missed 'readonly' opportunity Note

Field '_parser' can be 'readonly'.

Copilot Autofix

AI about 2 months ago

To fix this issue, add the readonly modifier to the field _parser. This ensures that _parser can only be set during the field's declaration or within the class's constructor, preventing unintended assignment elsewhere. Specifically, locate the declaration private FhirJsonDeserializer _parser; (line 23) in the file ImportResourceParser.cs and change it to private readonly FhirJsonDeserializer _parser;. No other code or imports need to be changed, as assignment occurs appropriately in the constructor.


Suggested changeset 1
src/Microsoft.Health.Fhir.Shared.Core/Features/Operations/Import/ImportResourceParser.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Shared.Core/Features/Operations/Import/ImportResourceParser.cs b/src/Microsoft.Health.Fhir.Shared.Core/Features/Operations/Import/ImportResourceParser.cs
--- a/src/Microsoft.Health.Fhir.Shared.Core/Features/Operations/Import/ImportResourceParser.cs
+++ b/src/Microsoft.Health.Fhir.Shared.Core/Features/Operations/Import/ImportResourceParser.cs
@@ -20,7 +20,7 @@
 {
     public class ImportResourceParser : IImportResourceParser
     {
-        private FhirJsonDeserializer _parser;
+        private readonly FhirJsonDeserializer _parser;
         private IResourceWrapperFactory _resourceFactory;
 
         public ImportResourceParser(FhirJsonDeserializer parser, IResourceWrapperFactory resourceFactory)
EOF
@@ -20,7 +20,7 @@
{
public class ImportResourceParser : IImportResourceParser
{
private FhirJsonDeserializer _parser;
private readonly FhirJsonDeserializer _parser;
private IResourceWrapperFactory _resourceFactory;

public ImportResourceParser(FhirJsonDeserializer parser, IResourceWrapperFactory resourceFactory)
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +30 to +37
if (resource is ResourceReference reference)
{
var childValue = child.Value;
if (childValue.TypeName == "Reference")
if (reference.Reference != null && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
{
var reference = (ResourceReference)childValue;
if (reference.Reference != null && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
{
reference.Reference = null;
reference.Display = "Referenced resource deleted";
}
reference.Reference = null;
reference.Display = "Referenced resource deleted";
}
else if (childValue.Children.Any())
}

Check notice

Code scanning / CodeQL

Nested 'if' statements can be combined Note

These 'if' statements can be combined.

Copilot Autofix

AI about 2 months ago

To fix the issue, combine the two if statements at lines 30 and 32 into a single conditional by combining their conditions with &&. Use proper parentheses to ensure correct operator precedence and take care that the inline variable (reference) declared by the pattern-matching is expression is only used if the type match succeeds. In recent C# versions, this is permitted directly in the conditional. Replace:

if (resource is ResourceReference reference)
{
    if (reference.Reference != null && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
    {
        // ...
    }
}

with:

if (resource is ResourceReference reference 
    && reference.Reference != null 
    && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
{
    // ...
}

Only lines within the method RemoveReferenceRecursive in file src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs need updating.

No additional imports, methods, or definitions are required.

Suggested changeset 1
src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs b/src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs
--- a/src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs
+++ b/src/Microsoft.Health.Fhir.Shared.Core/Features/Resources/Delete/ReferenceRemover.cs
@@ -27,13 +27,12 @@
             }
 
             // Check if this is a ResourceReference
-            if (resource is ResourceReference reference)
+            if (resource is ResourceReference reference
+                && reference.Reference != null
+                && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
             {
-                if (reference.Reference != null && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
-                {
-                    reference.Reference = null;
-                    reference.Display = "Referenced resource deleted";
-                }
+                reference.Reference = null;
+                reference.Display = "Referenced resource deleted";
             }
 
             // Recursively process all properties
EOF
@@ -27,13 +27,12 @@
}

// Check if this is a ResourceReference
if (resource is ResourceReference reference)
if (resource is ResourceReference reference
&& reference.Reference != null
&& reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
{
if (reference.Reference != null && reference.Reference.Equals(target, StringComparison.OrdinalIgnoreCase))
{
reference.Reference = null;
reference.Display = "Referenced resource deleted";
}
reference.Reference = null;
reference.Display = "Referenced resource deleted";
}

// Recursively process all properties
Copilot is powered by AI and may make mistakes. Always verify output.
reindexParameters.Add("targetResourcetype", new FhirString("Specimen"));
(reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);

Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning test

This assignment to
reindexJobUri
is useless, since its value is never read.

Copilot Autofix

AI about 2 months ago

To fix this problem, we should replace the assignment of the unused variable reindexJobUri in the tuple assignment with a discard (_). This makes it clear that the second value returned from RunReindexToCompletion is intentionally not used.

Specifically, in test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs, within the method shown, replace:

(reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);

with:

(reindexJobResult, _) = await RunReindexToCompletion(reindexParameters);

This eliminates the unnecessary assignment to reindexJobUri and avoids keeping unused local variables.

No changes to imports, methods, or other logic are required.


Suggested changeset 1
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
--- a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
+++ b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
@@ -284,13 +284,12 @@
                 searchParamPosted = await Client.CreateAsync(searchParam);
                 _output.WriteLine($"{nameof(searchParamPosted)} Response.StatusCode is {searchParamPosted.Response.StatusCode} and posted Url is {searchParam.Url}");
 
-                Uri reindexJobUri;
                 FhirResponse<Parameters> reindexJobResult;
 
                 // Start a reindex job
                 var reindexParameters = new Parameters();
                 reindexParameters.Add("targetResourcetype", new FhirString("Specimen"));
-                (reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);
+                (reindexJobResult, _) = await RunReindexToCompletion(reindexParameters);
 
                 Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);
                 Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
EOF
@@ -284,13 +284,12 @@
searchParamPosted = await Client.CreateAsync(searchParam);
_output.WriteLine($"{nameof(searchParamPosted)} Response.StatusCode is {searchParamPosted.Response.StatusCode} and posted Url is {searchParam.Url}");

Uri reindexJobUri;
FhirResponse<Parameters> reindexJobResult;

// Start a reindex job
var reindexParameters = new Parameters();
reindexParameters.Add("targetResourcetype", new FhirString("Specimen"));
(reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);
(reindexJobResult, _) = await RunReindexToCompletion(reindexParameters);

Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);
Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
Copilot is powered by AI and may make mistakes. Always verify output.

Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);
Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
Parameters.ParameterComponent resourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.Resources);

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning test

This assignment to
reindexJobUri
is useless, since its value is never read.

Copilot Autofix

AI about 2 months ago

To fix this issue, replace the assignment to the unused local variable reindexJobUri (which is never read) with a discard variable (_). This clarifies intent for anyone reading the code and avoids unnecessary local variable declarations. Locate the tuple assignment on line 408 in test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs where (reindexJobResult, reindexJobUri) = ... and change to (reindexJobResult, _) = .... Also, remove the declaration of reindexJobUri on line 402 since it is no longer needed. No additional imports or methods are needed; all required functionality is already present.


Suggested changeset 1
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
--- a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
+++ b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
@@ -399,13 +399,12 @@
                 searchParamPosted = await Client.CreateAsync(searchParam);
                 _output.WriteLine($"{nameof(searchParamPosted)} Response.StatusCode is {searchParamPosted.Response.StatusCode} and posted Url is {searchParam.Url}");
 
-                Uri reindexJobUri;
                 FhirResponse<Parameters> reindexJobResult;
 
                 // Start a reindex job
                 var reindexParameters = new Parameters();
                 reindexParameters.Add("targetResourceTypes", new FhirString("Specimen,Immunization"));
-                (reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);
+                (reindexJobResult, _) = await RunReindexToCompletion(reindexParameters);
 
                 Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);
                 Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
EOF
@@ -399,13 +399,12 @@
searchParamPosted = await Client.CreateAsync(searchParam);
_output.WriteLine($"{nameof(searchParamPosted)} Response.StatusCode is {searchParamPosted.Response.StatusCode} and posted Url is {searchParam.Url}");

Uri reindexJobUri;
FhirResponse<Parameters> reindexJobResult;

// Start a reindex job
var reindexParameters = new Parameters();
reindexParameters.Add("targetResourceTypes", new FhirString("Specimen,Immunization"));
(reindexJobResult, reindexJobUri) = await RunReindexToCompletion(reindexParameters);
(reindexJobResult, _) = await RunReindexToCompletion(reindexParameters);

Parameters.ParameterComponent searchParamListParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.SearchParams);
Parameters.ParameterComponent targetResourcesParam = reindexJobResult.Resource.Parameter.FirstOrDefault(p => p.Name == JobRecordProperties.TargetResourceTypes);
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +441 to +448
_output.WriteLine(error);
success = false;
await Task.Delay(TimeSpan.FromSeconds(10));
}
}
while (!success && retryCount < MaxRetryCount);

Assert.True(success, $"There are bundle validation failures. {retryCount} attempts reached. Check test logs.");

Check notice

Code scanning / CodeQL

Generic catch clause Note test

Generic catch clause.

Copilot Autofix

AI about 2 months ago

To fix this issue, the catch clause in the retry loop should be restricted to only catch specific exceptions that might realistically occur during validation and that are appropriate to handle with a retry. For this scenario, since the method being called interacts with a FHIR client and presumably does not expect programming errors, it should catch at minimum FhirClientException, and possibly exceptions like HttpRequestException. Unrecoverable exceptions (such as NullReferenceException, OutOfMemoryException, etc.) should not be caught or retried, as they represent serious bugs that should fail the test outright. The change should be in the file test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs, specifically replacing catch (Exception ex) on line 437 with more specific exception types. No new methods or definitions are required, and no new imports (the relevant exception types are already available in the context).

Suggested changeset 1
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
--- a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
+++ b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/CustomSearchParamTests.cs
@@ -434,7 +434,7 @@
 
                         _output.WriteLine($"Success on attempt {retryCount} of {MaxRetryCount}");
                     }
-                    catch (Exception ex)
+                    catch (FhirClientException ex)
                     {
                         string error = $"Attempt {retryCount} of {MaxRetryCount}: Failed to validate bundle: {ex}";
 
@@ -442,6 +442,14 @@
                         success = false;
                         await Task.Delay(TimeSpan.FromSeconds(10));
                     }
+                    catch (System.Net.Http.HttpRequestException ex)
+                    {
+                        string error = $"Attempt {retryCount} of {MaxRetryCount}: HTTP request failed during bundle validation: {ex}";
+
+                        _output.WriteLine(error);
+                        success = false;
+                        await Task.Delay(TimeSpan.FromSeconds(10));
+                    }
                 }
                 while (!success && retryCount < MaxRetryCount);
 
EOF
@@ -434,7 +434,7 @@

_output.WriteLine($"Success on attempt {retryCount} of {MaxRetryCount}");
}
catch (Exception ex)
catch (FhirClientException ex)
{
string error = $"Attempt {retryCount} of {MaxRetryCount}: Failed to validate bundle: {ex}";

@@ -442,6 +442,14 @@
success = false;
await Task.Delay(TimeSpan.FromSeconds(10));
}
catch (System.Net.Http.HttpRequestException ex)
{
string error = $"Attempt {retryCount} of {MaxRetryCount}: HTTP request failed during bundle validation: {ex}";

_output.WriteLine(error);
success = false;
await Task.Delay(TimeSpan.FromSeconds(10));
}
}
while (!success && retryCount < MaxRetryCount);

Copilot is powered by AI and may make mistakes. Always verify output.
}

var fhirJsonSerializer = new FhirJsonSerializer(new SerializerSettings() { AppendNewLine = false, Pretty = false });
var fhirJsonSerializer = new FhirJsonSerializer();

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning test

This assignment to
fhirJsonSerializer
is useless, since its value is never read.

Copilot Autofix

AI about 2 months ago

To fix this problem, simply remove the unused assignment var fhirJsonSerializer = new FhirJsonSerializer(); from line 329 in the method. This does not affect the program logic, since the instantiated object is never used, nor does its construction have any necessary, visible side-effect in this context. No other changes are needed elsewhere, and no imports or definitions need to be modified or added.

Suggested changeset 1
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SearchTestsBase.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SearchTestsBase.cs b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SearchTestsBase.cs
--- a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SearchTestsBase.cs
+++ b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/Search/SearchTestsBase.cs
@@ -326,7 +326,6 @@
                 }
             }
 
-            var fhirJsonSerializer = new FhirJsonSerializer();
             using var sw = new StringWriter(sb);
             sb.AppendLine("Actual collection as below -");
             foreach (var element in actualResources)
EOF
@@ -326,7 +326,6 @@
}
}

var fhirJsonSerializer = new FhirJsonSerializer();
using var sw = new StringWriter(sb);
sb.AppendLine("Actual collection as below -");
foreach (var element in actualResources)
Copilot is powered by AI and may make mistakes. Always verify output.
parameters.Parameter.Add(new Parameters.ParameterComponent() { Name = "profile", Value = new FhirString(profile) });

var parser = new FhirJsonParser();
var parser = new FhirJsonDeserializer();

Check warning

Code scanning / CodeQL

Useless assignment to local variable Warning test

This assignment to
parser
is useless, since its value is never read.

Copilot Autofix

AI about 2 months ago

To fix this issue, simply delete the line assigning parser = new FhirJsonDeserializer() on line 213. Since parser is not used elsewhere in the method, its declaration and instantiation are unnecessary. This change is contained within the file test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs, specifically within the method GivenInvalidProfile_WhenValidateCalled_ThenBadRequestReturned. No additional imports or method changes are needed.

Suggested changeset 1
test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs
--- a/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs
+++ b/test/Microsoft.Health.Fhir.Shared.Tests.E2E/Rest/ValidateTests.cs
@@ -210,7 +210,6 @@
             Parameters parameters = new Parameters();
             parameters.Parameter.Add(new Parameters.ParameterComponent() { Name = "profile", Value = new FhirString(profile) });
 
-            var parser = new FhirJsonDeserializer();
             parameters.Parameter.Add(new Parameters.ParameterComponent() { Name = "resource", Resource = Samples.GetDefaultPatient().ToPoco<Patient>() });
 
             exception = await Assert.ThrowsAsync<FhirClientException>(async () => await _client.ValidateAsync("Patient/$validate", parameters.ToJson()));
EOF
@@ -210,7 +210,6 @@
Parameters parameters = new Parameters();
parameters.Parameter.Add(new Parameters.ParameterComponent() { Name = "profile", Value = new FhirString(profile) });

var parser = new FhirJsonDeserializer();
parameters.Parameter.Add(new Parameters.ParameterComponent() { Name = "resource", Resource = Samples.GetDefaultPatient().ToPoco<Patient>() });

exception = await Assert.ThrowsAsync<FhirClientException>(async () => await _client.ValidateAsync("Patient/$validate", parameters.ToJson()));
Copilot is powered by AI and may make mistakes. Always verify output.
{
private ResourceWrapperFactory _resourceWrapperFactory;
private FhirJsonParser _fhirJsonParser;
private FhirJsonDeserializer _fhirJsonDeserializer;

Check notice

Code scanning / CodeQL

Missed 'readonly' opportunity Note

Field '_fhirJsonDeserializer' can be 'readonly'.

Copilot Autofix

AI about 2 months ago

The best way to fix the problem is to add the readonly modifier to the _fhirJsonDeserializer field declaration in ResourceWrapperParser.cs. This change clarifies the intent that this field cannot be reassigned after construction, aligns with best practices for immutability, and does not affect existing functionality since all assignments occur in the constructor. Specifically, change line 28 of the file to declare _fhirJsonDeserializer as private readonly FhirJsonDeserializer _fhirJsonDeserializer;. No new methods, imports, or other changes are required.


Suggested changeset 1
tools/Microsoft.Health.Fhir.R4.ResourceParser/ResourceWrapperParser.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/tools/Microsoft.Health.Fhir.R4.ResourceParser/ResourceWrapperParser.cs b/tools/Microsoft.Health.Fhir.R4.ResourceParser/ResourceWrapperParser.cs
--- a/tools/Microsoft.Health.Fhir.R4.ResourceParser/ResourceWrapperParser.cs
+++ b/tools/Microsoft.Health.Fhir.R4.ResourceParser/ResourceWrapperParser.cs
@@ -25,7 +25,7 @@
     public class ResourceWrapperParser
     {
         private ResourceWrapperFactory _resourceWrapperFactory;
-        private FhirJsonDeserializer _fhirJsonDeserializer;
+        private readonly FhirJsonDeserializer _fhirJsonDeserializer;
         private FhirJsonSerializer _fhirJsonSerializer;
         private IModelInfoProvider _modelInfoProvider;
 
EOF
@@ -25,7 +25,7 @@
public class ResourceWrapperParser
{
private ResourceWrapperFactory _resourceWrapperFactory;
private FhirJsonDeserializer _fhirJsonDeserializer;
private readonly FhirJsonDeserializer _fhirJsonDeserializer;
private FhirJsonSerializer _fhirJsonSerializer;
private IModelInfoProvider _modelInfoProvider;

Copilot is powered by AI and may make mistakes. Always verify output.
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