From 8446775dd5987f298cbafd7ae7dab5a5b52f617a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 12 May 2023 14:42:07 +0700 Subject: [PATCH] feat(developer): verify at least one language in package Adds `ERROR_MustHaveAtLeastOneLanguage` and corresponding unit test. --- .../kmc-package/src/compiler/kmp-compiler.ts | 29 ++++++++++--------- .../src/kmc-package/src/compiler/messages.ts | 4 +++ .../src/compiler/package-validation.ts | 5 ++++ ..._must_have_at_least_one_language.model.kps | 28 ++++++++++++++++++ .../kmc-package/test/test-package-compiler.ts | 7 +++++ 5 files changed, 60 insertions(+), 13 deletions(-) create mode 100644 developer/src/kmc-package/test/fixtures/invalid/keyman.en.error_must_have_at_least_one_language.model.kps diff --git a/developer/src/kmc-package/src/compiler/kmp-compiler.ts b/developer/src/kmc-package/src/compiler/kmp-compiler.ts index 305a1faaa1..b660641df9 100644 --- a/developer/src/kmc-package/src/compiler/kmp-compiler.ts +++ b/developer/src/kmc-package/src/compiler/kmp-compiler.ts @@ -105,16 +105,16 @@ export class KmpCompiler { // if(kps.keyboards && kps.keyboards.keyboard) { - kmp.keyboards = this.arrayWrap(kps.keyboards.keyboard).map((keyboard: KpsFile.KpsFileKeyboard) => { - return { - displayFont: keyboard.displayFont ? this.callbacks.path.basename(keyboard.displayFont) : undefined, - oskFont: keyboard.oSKFont ? this.callbacks.path.basename(keyboard.oSKFont) : undefined, - name:keyboard.name, - id:keyboard.iD, - version:keyboard.version, - languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(keyboard.languages.language) as KpsFile.KpsFileLanguage[]) - }; - }); + kmp.keyboards = this.arrayWrap(kps.keyboards.keyboard).map((keyboard: KpsFile.KpsFileKeyboard) => ({ + displayFont: keyboard.displayFont ? this.callbacks.path.basename(keyboard.displayFont) : undefined, + oskFont: keyboard.oSKFont ? this.callbacks.path.basename(keyboard.oSKFont) : undefined, + name:keyboard.name, + id:keyboard.iD, + version:keyboard.version, + languages: keyboard.languages ? + this.kpsLanguagesToKmpLanguages(this.arrayWrap(keyboard.languages.language) as KpsFile.KpsFileLanguage[]) : + [] + })); } // @@ -122,9 +122,12 @@ export class KmpCompiler { // if(kps.lexicalModels && kps.lexicalModels.lexicalModel) { - kmp.lexicalModels = this.arrayWrap(kps.lexicalModels.lexicalModel).map((model: KpsFile.KpsFileLexicalModel) => { - return { name:model.name, id:model.iD, languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(model.languages.language) as KpsFile.KpsFileLanguage[]) } - }); + kmp.lexicalModels = this.arrayWrap(kps.lexicalModels.lexicalModel).map((model: KpsFile.KpsFileLexicalModel) => ({ + name:model.name, + id:model.iD, + languages: model.languages ? + this.kpsLanguagesToKmpLanguages(this.arrayWrap(model.languages.language) as KpsFile.KpsFileLanguage[]) : [] + })); } // diff --git a/developer/src/kmc-package/src/compiler/messages.ts b/developer/src/kmc-package/src/compiler/messages.ts index ec8ce08af8..607af21eb9 100644 --- a/developer/src/kmc-package/src/compiler/messages.ts +++ b/developer/src/kmc-package/src/compiler/messages.ts @@ -94,5 +94,9 @@ export class CompilerMessages { static Warn_LanguageTagIsNotMinimal = (o: {resourceType: string, id:string, actual:string, expected:string}) => m(this.WARN_LanguageTagIsNotMinimal, `Language tag '${o.actual}' in ${o.resourceType} ${o.id} is not minimal, and should be '${o.expected}'.`); static WARN_LanguageTagIsNotMinimal = SevWarn | 0x0015; + + static Error_MustHaveAtLeastOneLanguage = (o:{resourceType:string, id:string}) => m(this.ERROR_MustHaveAtLeastOneLanguage, + `The ${o.resourceType} ${o.id} must have at least one language specified.`); + static ERROR_MustHaveAtLeastOneLanguage = SevError | 0x0016; } diff --git a/developer/src/kmc-package/src/compiler/package-validation.ts b/developer/src/kmc-package/src/compiler/package-validation.ts index cfacf95cd4..96990f2097 100644 --- a/developer/src/kmc-package/src/compiler/package-validation.ts +++ b/developer/src/kmc-package/src/compiler/package-validation.ts @@ -44,6 +44,11 @@ export class PackageValidation { private checkForDuplicatedOrNonMinimalLanguages(resourceType: 'keyboard'|'model', id: string, languages: KmpJsonFile.KmpJsonFileLanguage[]): boolean { let minimalTags: {[tag: string]: string} = {}; + if(languages.length == 0) { + this.callbacks.reportMessage(CompilerMessages.Error_MustHaveAtLeastOneLanguage({resourceType, id})); + return false; + } + for(let lang of languages) { let locale; try { diff --git a/developer/src/kmc-package/test/fixtures/invalid/keyman.en.error_must_have_at_least_one_language.model.kps b/developer/src/kmc-package/test/fixtures/invalid/keyman.en.error_must_have_at_least_one_language.model.kps new file mode 100644 index 0000000000..b79330f06f --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/keyman.en.error_must_have_at_least_one_language.model.kps @@ -0,0 +1,28 @@ + + + + 15.0.266.0 + 7.0 + + + SENĆOŦEN (Saanich Dialect) Lexical Model + © 2019 National Research Council Canada + Eddie Antonio Santos + 1.0.3 + + + + example.qaa.sencoten.model.js + Lexical model example.qaa.sencoten.model.js + 0 + .model.js + + + + + SENĆOŦEN dictionary + example.qaa.sencoten + + + + diff --git a/developer/src/kmc-package/test/test-package-compiler.ts b/developer/src/kmc-package/test/test-package-compiler.ts index 95e6e3f9f0..8a81d56b7c 100644 --- a/developer/src/kmc-package/test/test-package-compiler.ts +++ b/developer/src/kmc-package/test/test-package-compiler.ts @@ -296,4 +296,11 @@ describe('KmpCompiler', function () { it('should generate WARN_LanguageTagIsNotMinimal if keyboard has a non-minimal language tag', async function() { testForMessage(this, ['invalid', 'warn_language_tag_is_not_minimal.kps'], CompilerMessages.WARN_LanguageTagIsNotMinimal); }); + + // ERROR_MustHaveAtLeastOneLanguage + + it('should generate ERROR_MustHaveAtLeastOneLanguage if model or keyboard has zero language tags', async function() { + testForMessage(this, ['invalid', 'keyman.en.error_must_have_at_least_one_language.model.kps'], + CompilerMessages.ERROR_MustHaveAtLeastOneLanguage); + }); });