-
Notifications
You must be signed in to change notification settings - Fork 43
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
Support Context keyword when defining Extensions #1282
Conversation
The Context keyword is used to specify the contexts in which the Extension should be used. Add the keyword to the grammar definition. Store contexts with source info when importing FSH.
Contexts specified with the Context keyword are applied to Extensions during export. If the value is quoted, it is a "fhirpath" context. If the value is not quoted and resolves to an Extension definition, it is an "extension" context. Otherwise, it is an "element" context.
The Context keyword is used at most once per extension. This is similar to other metadata keywords. To provide multiple contexts, a comma-separated list can be provided.
When using the Context keyword on an Extension, validate that the extension or element specified is something that actually exists. The element is specified by a FSH path, but is exported as a FHIR element id. Always use the resource id when the context is an element on a core FHIR resource. Otherwise, use the URL followed by an element id.
A complex extension may contain more than one level of extension elements. Traverse the extension by url to find deeply nested extensions. When an element path is given as context, it may represent a deeply nested extension. If so, set the context as extension context. The element counts as a deeply nested extension if every element along its path is also an extension.
Contained extensions must be specified the same as any other element by using a FSH path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really good! I had a few comments inline, as well as this:
One other thing related to this feature: while reviewing this, I realized that we need to add Context
to the keywords that get highlighted in the VS Code extension. Ideally, I think we could release a new version of the extension around the same time, or even before, we release this feature in SUSHI.
'Could not find resource MysteryExtension to use as extension context.' | ||
); | ||
expect(loggerSpy.getLastMessage('error')).toMatch(/File: Context\.fsh.*Line: 8\D*/s); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last test in the custom resource block reminded me of possibly another test case that might be useful in this section. Is it worthwhile also testing that an invalid FSH path on a resource? I think the error will be triggered by the same logic, so it might be a duplicate test, so curious what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think adding that type of test would be redundant? I'm still just curious to hear what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really nice implementation of a tricky feature. Very well done. I think you did a great job leveraging some of the functions we already had, resulting in a very clean implementation.
I've left a few comments for your consideration. Thank you!
Only set the default context if the Context keyword is unused and there is no existing context. Assume that the last # present in an unquoted context is what separates the URL from the path. This helps with URLs that contain a # character.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything is looking really good! I just found one small bit of dead code that can probably be deleted.
src/fshtypes/Extension.ts
Outdated
const contextLines: string[] = []; | ||
this.contexts.forEach(extContext => { | ||
if (extContext.isQuoted) { | ||
contextLines.push(`Context: "${fshifyString(extContext.value)}"`); | ||
} else { | ||
contextLines.push(`Context: ${extContext.value}`); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, this is dead code now and can be deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only wanted to check in one outstanding question, other than what Chris mentioned.
'Could not find resource MysteryExtension to use as extension context.' | ||
); | ||
expect(loggerSpy.getLastMessage('error')).toMatch(/File: Context\.fsh.*Line: 8\D*/s); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think adding that type of test would be redundant? I'm still just curious to hear what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just did some manual testing on this, and unfortunately, it looks like it's not quite ready yet.
Given an extension with multiple contexts like this:
Extension: Foo
Context: Patient, Practitioner, "some.fhirpath"
* value[x] only boolean
We get the following parse errors:
error token recognition error at: ' '
File: /Users/cmoesel/data/fsh/ScratchPad/input/fsh/scratch.fsh
Line: 12
error token recognition error at: ' '
File: /Users/cmoesel/data/fsh/ScratchPad/input/fsh/scratch.fsh
Line: 12
It also emits errors if we try to separate them on separate lines (one error for every space character).
So... we'll hold this feature back for SUSHI 3.1.0.
Id: some-extension | ||
Context: "some.fhirpath()", Observation.component, http://example.org/MyPatient#identifier, | ||
"another.fhirpath(var, 0)" | ||
`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add an assertion that confirms that no errors are emitted. As of now, this test does produce errors because the parser doesn't know what to do w/ the spaces between the contexts.
Remove unused code from Extension toFSH method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixes #1259 and completes task CIMPL-1090.
This adds the new
Context
keyword that can be used when defining an Extension. The value of the context can be specified in a few different ways:#
and a FSH pathMultiple contexts can be specified in a comma-separated list.
The resulting
type
of the context depends on what is specified:fhirpath
type is always used.extension
type is used.element
type is used.This allows for some flexibility for how authors specify the context, while consistently resolving contexts to the more specific
extension
type whenever possible. The included test cases demonstrate this flexibility.For more information about extension contexts, the official documentation provides some useful details.