Repository: FHIR/sushi (ts)

Issue:
No easy way to put a caret rule on the root element
Sometimes authors might want to assign a `short` description on the root element.  Usually our syntax for setting a short on an element is:
```
* path ^short = "My short description"
```
For the root element, there is no path -- but if we leave it blank, it's interpreted as being on the SD itself (not the root element).

This *might* work if you do:
```
* ^snapshot.element.short = "My short description"
```
but honestly, I'm not sure due to the way we do elements in the `StructureDefinition` class.

At a minimum, we should ensure the workaround works, but ideally we should define a syntax to access the root element.

Pull request description:
Apply CaretValueRule to parent element with .
Fixes #277 and completes task https://standardhealthrecord.atlassian.net/browse/CIMPL-313

When a path of "." is used in a CaretValueRule, the rule is applied to the parent element in the structure definition. This is distinct from an empty path "", where the rule is applied to the structure definition itself.

Patch:
diff --git a/src/fhirtypes/StructureDefinition.ts b/src/fhirtypes/StructureDefinition.ts
index 8b556da..fe34241 100644
--- a/src/fhirtypes/StructureDefinition.ts
+++ b/src/fhirtypes/StructureDefinition.ts
@@ -173,7 +173,7 @@ export class StructureDefinition {
   findElementByPath(path: string, fisher: Fishable): ElementDefinition {
     // If the path already exists, get it and return the match
     // If !path just return the base parent element
-    const fullPath = path ? `${this.type}.${path}` : this.type;
+    const fullPath = path && path !== '.' ? `${this.type}.${path}` : this.type;
     const match = this.elements.find(e => e.path === fullPath && !e.id.includes(':'));
     if (match != null) {
       return match;


Test patch:
diff --git a/test/export/StructureDefinitionExporter.test.ts b/test/export/StructureDefinitionExporter.test.ts
index f94c35e..b672d1d 100644
--- a/test/export/StructureDefinitionExporter.test.ts
+++ b/test/export/StructureDefinitionExporter.test.ts
@@ -1930,6 +1930,24 @@ describe('StructureDefinitionExporter', () => {
     expect(loggerSpy.getLastMessage()).toMatch(/File: InvalidValue\.fsh.*Line: 6\D*/s);
   });
 
+  it('should apply a CaretValueRule on the parent element', () => {
+    // Profile: ShortObservation
+    // Parent: Observation
+    // * . ^ short = "This one is not so tall."
+    const profile = new Profile('ShortObservation');
+    profile.parent = 'Observation';
+
+    const rule = new CaretValueRule('.');
+    rule.caretPath = 'short';
+    rule.value = 'This one is not so tall.';
+    profile.rules.push(rule);
+
+    exporter.exportStructDef(profile);
+    const sd = pkg.profiles[0];
+    const observation = sd.findElement('Observation');
+    expect(observation.short).toBe('This one is not so tall.');
+  });
+
   it('should apply a CaretValueRule on an element without a path', () => {
     const profile = new Profile('Foo');
     profile.parent = 'Observation';