diff --git a/common/web/types/src/kmx/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus.ts index 020d5fb330..d7e21a5097 100644 --- a/common/web/types/src/kmx/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus.ts @@ -150,6 +150,21 @@ export class Vars extends Section { strings: StringVarItem[] = []; // ≠ StrsItem sets: SetVarItem[] = []; unicodeSets: UnicodeSetItem[] = []; + + /** + * + * @returns false if any invalid variables + */ + valid() : boolean { + for (const t of [this.sets, this.strings, this.unicodeSets]) { + for (const i of t) { + if (!i.valid()) { + return false; + } + } + } + return true; + } }; /** @@ -165,6 +180,10 @@ class VarsItem extends Section { this.id = sections.strs.allocString(id); this.value = sections.strs.allocAndUnescapeString(value); } + + valid() : boolean { + return true; + } }; export class UnicodeSetItem extends VarsItem { @@ -177,14 +196,20 @@ export class UnicodeSetItem extends VarsItem { // A message will have been set in that case. } _unicodeSet?: UnicodeSet; + valid() : boolean { + return !!this._unicodeSet; + } }; export class SetVarItem extends VarsItem { constructor(id: string, value: string, sections: GlobalSections) { super(id, value, sections); - this._items = null; // TODO-LDML + this._items = value.split(' '); // TODO-LDML + } + _items: string[]; + valid() : boolean { + return !!this._items; } - _items: string; }; export class StringVarItem extends VarsItem { diff --git a/developer/src/kmc-kmn/src/main.ts b/developer/src/kmc-kmn/src/main.ts index c3c3d6f173..53e629929d 100644 --- a/developer/src/kmc-kmn/src/main.ts +++ b/developer/src/kmc-kmn/src/main.ts @@ -1,2 +1,3 @@ export { Compiler } from './compiler/compiler.js'; +export { CompilerMessages } from './compiler/messages.js'; diff --git a/developer/src/kmc-ldml/src/compiler/messages.ts b/developer/src/kmc-ldml/src/compiler/messages.ts index abd2325aa1..c937dbfa04 100644 --- a/developer/src/kmc-ldml/src/compiler/messages.ts +++ b/developer/src/kmc-ldml/src/compiler/messages.ts @@ -91,7 +91,7 @@ export class CompilerMessages { static ERROR_MissingFlicks = SevError | 0x0015; static Error_DuplicateVariable = (o:{ids: string}) => m(this.ERROR_DuplicateVariable, - `duplicate variable id=${o.ids}`); + `duplicate variables: id=${o.ids}`); static ERROR_DuplicateVariable = SevError | 0x0016; static Fatal_SectionInitFailed = (o:{sect: string}) => diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts index 52466a14e7..09a7f5ff01 100644 --- a/developer/src/kmc-ldml/src/compiler/vars.ts +++ b/developer/src/kmc-ldml/src/compiler/vars.ts @@ -54,7 +54,7 @@ export class VarsCompiler extends SectionCompiler { // one report if any dups if (dups.size > 0) { this.callbacks.reportMessage(CompilerMessages.Error_DuplicateVariable({ - ids: Array.of(dups.values()).join(', ') + ids: Array.from(dups.values()).sort().join(', ') })); valid = false; } @@ -80,6 +80,10 @@ export class VarsCompiler extends SectionCompiler { variables?.unicodeSet?.map(({ id, value }) => new UnicodeSetItem(id, value, sections, this.usetparser)); - return result; + if (!result.valid()) { + return null; + } else { + return result; + } } } diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props1.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props1.xml new file mode 100644 index 0000000000..c7930181d3 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props1.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props2.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props2.xml new file mode 100644 index 0000000000..761c2251c3 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-props2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-strings.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-strings.xml new file mode 100644 index 0000000000..a207df13f1 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-strings.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-syntax.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-syntax.xml new file mode 100644 index 0000000000..0fd29f5bab --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-uset-syntax.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/helpers/index.ts b/developer/src/kmc-ldml/test/helpers/index.ts index fc85323261..2b03b3c092 100644 --- a/developer/src/kmc-ldml/test/helpers/index.ts +++ b/developer/src/kmc-ldml/test/helpers/index.ts @@ -19,6 +19,7 @@ import GlobalSections = KMXPlus.GlobalSections; import Section = KMXPlus.Section; import Strs = KMXPlus.Strs; import List = KMXPlus.List; +// import Vars = KMXPlus.Vars; /** * Builds a path to the fixture with the given path components. @@ -70,11 +71,10 @@ export async function loadSectionFixture(compilerClass: typeof SectionCompiler, strs: new Strs(), elem: null, list: null, - vars: null, + vars: null, // ? }; globalSections.elem = new Elem(globalSections.strs); globalSections.list = new List(globalSections.strs); - globalSections.vars = null; // new Vars(globalSections.strs); return compiler.compile(globalSections); } @@ -175,7 +175,7 @@ export function testCompilationCases(compiler: typeof SectionCompiler, cases : C } let section = await loadSectionFixture(compiler, testcase.subpath, callbacks); if (expectFailure) { - assert.isNull(section, 'expected compilation result to be null, but got something'); + assert.isNull(section, 'expected compilation result failure (null)'); } else { assert.isNotNull(section, `expected successful compilation, but got null and ${JSON.stringify(callbacks.messages)}`); } diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index c81060abb5..9c2e5c3e1b 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -1,7 +1,8 @@ import 'mocha'; import { assert } from 'chai'; import { VarsCompiler } from '../src/compiler/vars.js'; -// import { CompilerMessages } from '../src/compiler/messages.js'; +import { CompilerMessages } from '../src/compiler/messages.js'; +import { CompilerMessages as KmnCompilerMessages } from '@keymanapp/kmc-kmn'; import { /*compilerTestCallbacks, loadSectionFixture,*/testCompilationCases } from './helpers/index.js'; import { KMXPlus /*, CommonTypesMessages*/ } from '@keymanapp/common-types'; // import { constants } from '@keymanapp/ldml-keyboard-constants'; @@ -32,11 +33,39 @@ describe('vars', function () { }, { subpath: 'sections/vars/dup0.xml', - errors: [], + errors: [ + CompilerMessages.Error_DuplicateVariable({ids: 'y'}) + ], }, { subpath: 'sections/vars/dup1.xml', - errors: [], + errors: [ + CompilerMessages.Error_DuplicateVariable({ids: 'upper, y'}) + ], + }, + { + subpath: 'sections/vars/fail-uset-props1.xml', + errors: [ + KmnCompilerMessages.Error_UnicodeSetHasProperties() + ], + }, + { + subpath: 'sections/vars/fail-uset-props2.xml', + errors: [ + KmnCompilerMessages.Error_UnicodeSetHasProperties() + ], + }, + { + subpath: 'sections/vars/fail-uset-strings.xml', + errors: [ + KmnCompilerMessages.Error_UnicodeSetHasStrings() + ], + }, + { + subpath: 'sections/vars/fail-uset-syntax.xml', + errors: [ + KmnCompilerMessages.Error_UnicodeSetSyntaxError() + ], }, ]); });