Repository: FHIR/sushi (ts)

Issue:
SUSHI instances don't like profiles w/ slicename matching path name(?)
See Zulip Thread: https://chat.fhir.org/#narrow/stream/215610-shorthand/topic/error.20The.20element.20or.20path.20you.20referenced.20does.20not.20exist

After some investigation, I figured out that the problem occurs when the slicename matches the path name.  E.g., when `contact` is sliced with a slicename called `contact`.  Renaming the slicename to `contact2` fixes it!

Small reproducible sample: https://fshschool.org/FSHOnline/#/share/3egT4Lo

Pull request description:
Do not be fooled by slices with the same name as the sliced element
Fixes #993

When finding an element by path, it is permitted to use the name of a choice element slice (such as `valueString`) directly in a path. This is achieved by considering elements to match when the element id contains the appropriate path part and slice name (`value[x]:valueString`, for example). However, this should only be supported for choice elements, so do not consider an element to be a match when the name of the slice and the name of the element are the same.

Basically, without this change, the "remove slices" filter wouldn't remove the slice that had the same name as the element. Also, the bug only occurs when looking for a sufficiently deep descendant of the sliced element. What a thrill!

Patch:
diff --git a/src/fhirtypes/StructureDefinition.ts b/src/fhirtypes/StructureDefinition.ts
index 3b8a639..35966bc 100644
--- a/src/fhirtypes/StructureDefinition.ts
+++ b/src/fhirtypes/StructureDefinition.ts
@@ -301,7 +301,11 @@ export class StructureDefinition {
           // If matchingElement id ends with pathEnd:, then it is a slice
           // pathPart.brackets is null, so keep nonslices (no ":" in idEnd)
           // and choice slices since valueString is equivalent to value[x]:valueString
-          return !idEnd.includes(`${pathEnd}:`) || idEnd === `${pathEnd}:${pathPart.base}`;
+          // but, make sure to not be fooled by slices where the slice name is the same as the element name
+          return (
+            !idEnd.includes(`${pathEnd}:`) ||
+            (idEnd === `${pathEnd}:${pathPart.base}` && pathEnd !== pathPart.base)
+          );
         });
       }
     }


Test patch:
diff --git a/test/fhirtypes/StructureDefinition.test.ts b/test/fhirtypes/StructureDefinition.test.ts
index 93e90dc..15cdfac 100644
--- a/test/fhirtypes/StructureDefinition.test.ts
+++ b/test/fhirtypes/StructureDefinition.test.ts
@@ -974,6 +974,19 @@ describe('StructureDefinition', () => {
       expect(respRate.elements.length).toBe(originalLength);
     });
 
+    it('should find an element that is the grandchild or deeper descendant of an element that has a slice with the same name as the ancestor element', () => {
+      const component = respRate.findElementByPath('component', fisher);
+      component.slicing = {
+        discriminator: [{ type: 'pattern', path: '$this' }],
+        rules: 'open'
+      };
+      component.addSlice('component');
+      // force an unfolding by finding a descendant of the slice
+      respRate.findElementByPath('component[component].dataAbsentReason', fisher);
+      const descendant = respRate.findElementByPath('component.referenceRange.low', fisher);
+      expect(descendant).toBeDefined();
+    });
+
     it('should find a re-sliced element by path', () => {
       const jsonReslice = JSON.parse(
         fs.readFileSync(