Appearance
Name analysis
Works out which names exist in a Questionnaire, which of them each expression can reference, and how they depend on each other. It also lists the form's linkIds and the expressions that refer to them. It runs once per Questionnaire, before the rules, and the rules read its answers.
A declaration introduces a name that other expressions reference as %name. It can be a named expression at a catalogued location, such as a variable or an itemPopulationContext, a launchContext on the root, or an extractAllocateId. A sourceQueries result is not a declaration: the software running the form supplies it, so it is a host variable, listed in the config or supplied by a plugin.
An expression can reference:
- the declarations on its own element, on the items above it and on the root, the nearest one winning when names repeat;
- the names FHIRPath, FHIR and SDC define, such as
%resource,%context,%questionnaireand%qitem, and any name startingvs-orext-; - the names a module's
assembleContextlists; - the host variables: the config's
hostVariables, and the names plugins supply through theirhostVariableshook, such as the Smart Forms sourceQueries names. A declaration or anassembleContextname of the same name wins.
A host variable cannot be a name FHIRPath, FHIR or SDC defines: in the config it is a CONFIG_INVALID error, and from a plugin it is dropped. A plugin hook that fails stops the run with PLUGIN_CRASH.
An extraction expression sees only the extraction names; any other expression sees all the declarations except them. An uncatalogued expression gets no answer, because its scope is not known.
| What it works out | Read by |
|---|---|
| The declarations, in document order | sdc/duplicate-declaration, sdc/shadowed-declaration, sdc/reserved-name |
The %name references of each FHIRPath expression, and the names available there | sdc/undefined-variable |
| What each declaration's expression references | sdc/dependency-cycle, smart-forms/forward-variable-reference |
Whether others reference each declaration: referenced, unreferenced, blocked or unknown | sdc/unused-declaration, smart-forms/repeating-group-variable |
| Whether a FHIRPath expression reads its input other than its linkId, so it can give each repetition of a group a different value | smart-forms/repeating-group-variable, smart-forms/forward-variable-reference |
The form's linkIds, and the where(linkId = …) references | sdc/unresolved-linkid |
When a question cannot be answered for certain, for example after a defineVariable with a computed name, the answer says so, and the rules stay silent rather than guess.
Schema
Plugin rules get the declarations, references, available variables, dependencies, uses and input reads through RuleContext, but not the linkId analysis. What a plugin can import describes it.
Code
In packages/core/src/analysis/:
document-analysis.ts:analyseDocumentruns the steps below once per Questionnaire, and returns theDocumentAnalysis.declarations.ts:findDeclarationslists the declarations;findAssembleContextNameslists a module'sassembleContextnames.available-variables.ts:availableVariablesgives the names available at each site, and the built-in names.definerOfsays which specification defines a name; plugins can import it.dependencies.ts:findDependenciesrecords what each declaration references.uses.ts:findUsesrecords whether each declaration is referenced.linkids.ts:findLinkIdslists the items' linkIds;findLinkIdReferencesAtgives the linkId references of each site.run/host-variables.ts:suppliedHostVariablescalls a plugin'shostVariableshook and checks its result;lint.tsadds the names to the config's before the analysis.
Expression discovery in the architecture map has the full scope rules.