diff --git a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts index 1d19cdd4d0..d5b999ddee 100644 --- a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts @@ -291,7 +291,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 fb9b2f7596..39bc9304af 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(LdmlCompilerMessages.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 0000000000..25e7c46a1d --- /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 42b5d7df80..d513574ee8 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 () { LdmlCompilerMessages.Error_MissingStringVariable({id: 'missingStringInSet'}) ], }, - ], varsDependencies); + { + subpath: 'sections/vars/fail-badref-7.xml', + errors: [ + LdmlCompilerMessages.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 5435e32286..8cf2234fd3 100644 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts @@ -153,7 +153,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` @@ -165,8 +165,8 @@ describe('visual-keyboard-compiler', function() { - + `; @@ -177,7 +177,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` @@ -192,8 +192,8 @@ describe('visual-keyboard-compiler', function() { - + `;