Repository: FHIR/sushi (ts)

Issue:
Improve error message for code caret rule on ValueSet compose component without any concept
When writing rules for a ValueSet, it is invalid to make a code caret rule on a concept that is not specifically present within the ValueSet.. However, when there are _no_ specific concepts present, a slightly strange error message is produced.

Sample FSH:
```
ValueSet: SomeVS
* include codes from system http://example.org/CS
* http://example.org/CS#"some-code" ^designation.value = "some value"
```

Error message received:
```
error The element or path you referenced does not exist: compose.include[0].concept[undefined].designation.value
  Line: 3
```
The rule path in the error message is the path constructed within the ValueSetExporter for the rule on line 3. But, it might be more useful to directly indicate that the rule is invalid because there is no concept array in the compose element with `http://example.org/CS` as the system.

Pull request description:
Improve error message for ValueSet compose component without any concept
**Description:** This PR adds an improved error message for when there is a code caret rule on ValueSet where the compose component does not have a concept.

**Testing Instructions:** Run unit tests.

**Related Issue:** This fixes #1518 .


Patch:
diff --git a/src/export/ValueSetExporter.ts b/src/export/ValueSetExporter.ts
index 88769a6..9a6019e 100644
--- a/src/export/ValueSetExporter.ts
+++ b/src/export/ValueSetExporter.ts
@@ -457,7 +457,15 @@ export class ValueSetExporter {
           });
         }
       }
-
+      if (conceptIndex == null) {
+        logger.error(
+          `Cannot process caret assignment rule for code ${system}#${code} because ` +
+            'this value set does not explicitly include or exclude this code in its ' +
+            'rules. To fix this error, add a rule that specifically includes or excludes ' +
+            'this code for the value set.'
+        );
+        return;
+      }
       if (conceptIndex !== -1) {
         if (rule.isInstance) {
           const instanceExporter = new InstanceExporter(this.tank, this.pkg, this.fisher);


Test patch:
diff --git a/test/export/ValueSetExporter.test.ts b/test/export/ValueSetExporter.test.ts
index 6e06905..ffb34b7 100644
--- a/test/export/ValueSetExporter.test.ts
+++ b/test/export/ValueSetExporter.test.ts
@@ -754,6 +754,34 @@ describe('ValueSetExporter', () => {
     });
   });
 
+  it('should throw error for caret rule on valueset compose component without any concept', () => {
+    // ValueSet: SomeVS
+    // * include codes from system http://example.org/CS
+    // * http://example.org/CS#"some-code" ^designation.value = "some value"
+
+    const valueSet = new FshValueSet('SomeVS');
+
+    const component = new ValueSetConceptComponentRule(true);
+    component.from.system = 'http://example.org/CS';
+
+    const cvRule = new CaretValueRule('');
+    cvRule.pathArray = ['http://example.org/CS#"some-code"'];
+    cvRule.caretPath = 'designation.value';
+    cvRule.value = 'some value';
+
+    valueSet.rules.push(component, cvRule);
+    doc.valueSets.set(valueSet.name, valueSet);
+    const exported = exporter.export().valueSets;
+    expect(exported.length).toBe(1);
+    expect(loggerSpy.getAllMessages('error')).toHaveLength(1);
+    expect(loggerSpy.getLastMessage('error')).toBe(
+      'Cannot process caret assignment rule for code http://example.org/CS#"some-code" ' +
+        'because this value set does not explicitly include or exclude this code in its ' +
+        'rules. To fix this error, add a rule that specifically includes or excludes this ' +
+        'code for the value set.'
+    );
+  });
+
   it('should export a value set with a contained resource created on the value set', () => {
     // ValueSet: DinnerVS
     // * ^contained.resourceType = "Observation"