diff --git a/common/web/types/src/kmx/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus.ts index 6e3c73d33c8..42dc7305a7c 100644 --- a/common/web/types/src/kmx/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus.ts @@ -285,7 +285,7 @@ export class Vars extends Section { }); } findStringVariableValue(id: string): string { - return Vars.findVariable(this.strings, id)?.value?.value; // Unwrap: Variable, StrsItem + return Vars.findVariable(this.strings, id)?.value?.value ?? null; // Unwrap: Variable, StrsItem } substituteSetRegex(str: string, sections: DependencySections): string { return str.replaceAll(VariableParser.SET_REFERENCE, (_entire, id) => { diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts index 34fa99831ba..d640dbf1a35 100644 --- a/developer/src/kmc-ldml/src/compiler/vars.ts +++ b/developer/src/kmc-ldml/src/compiler/vars.ts @@ -68,9 +68,16 @@ export class VarsCompiler extends SectionCompiler { // Strings for (const { id, value } of variables.string) { addId(id); - allStrings.add(id); const stringrefs = VariableParser.allStringReferences(value); + for(const ref of stringrefs) { + if(!allStrings.has(ref)) { + valid = false; + this.callbacks.reportMessage(CompilerMessages.Error_MissingStringVariable({id: ref})); + allStrings.add(ref); // avoids multiple reports of same missing variable + } + } st.string.add(SubstitutionUse.variable, stringrefs); + allStrings.add(id); } // Sets for (const { id, value } of variables.set) { diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml new file mode 100644 index 00000000000..25e7c46a1d4 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index e3ac53c4a92..b1fadd0e448 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -187,7 +187,14 @@ describe('vars', function () { CompilerMessages.Error_MissingStringVariable({id: 'missingStringInSet'}) ], }, - ], varsDependencies); + { + subpath: 'sections/vars/fail-badref-7.xml', + errors: [ + CompilerMessages.Error_MissingStringVariable({id: 'usedBeforeDefinition'}) + ], + strictErrors: true + }, +], varsDependencies); describe('should match some marker constants', () => { // neither of these live here, but, common/web/types does not import ldml-keyboard-constants otherwise. diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts index dee096cb221..ab412f1396d 100644 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts @@ -159,7 +159,7 @@ describe('visual-keyboard-compiler', function() { assert.equal(vk.keys[1].text, '\u{0e81}'); }); - it.skip('should read string variables in key.output', async function() { + it('should read string variables in key.output', async function() { const xml = stripIndent` @@ -171,8 +171,8 @@ describe('visual-keyboard-compiler', function() { - + `; @@ -183,7 +183,7 @@ describe('visual-keyboard-compiler', function() { assert.equal(vk.keys[0].text, '2'); }); - it.skip('should read string variables in display.display', async function() { + it('should read string variables in display.display', async function() { const xml = stripIndent` @@ -198,8 +198,8 @@ describe('visual-keyboard-compiler', function() { - + `;