From f438a519e16cdd9fae6507fee8e5e8ee06c91b0d Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 1 Sep 2026 10:14:11 +0200 Subject: [PATCH] fix(developer): add missing message parameters and cleanup kmc-kmn messages further * kmcmplib messages need to use a standard pattern for parameters, which cannot be named. Several of the messages had the wrong pattern * Tidy up the kmn-compiler-messages module and make it more consistent to reduce risk of this happening in the future * Add a unit test to further verify the structure of the module as far as possible Fixes: #16492 Test-bot: skip --- .../web/utils/src/compiler-interfaces.ts | 2 +- .../src/compiler/kmn-compiler-messages.ts | 543 ++++++++++-------- .../test/kmn-compiler-messages.tests.ts | 64 ++- 3 files changed, 382 insertions(+), 227 deletions(-) diff --git a/developer/src/common/web/utils/src/compiler-interfaces.ts b/developer/src/common/web/utils/src/compiler-interfaces.ts index d7081b815a..c79862842a 100644 --- a/developer/src/common/web/utils/src/compiler-interfaces.ts +++ b/developer/src/common/web/utils/src/compiler-interfaces.ts @@ -59,7 +59,7 @@ export enum CompilerErrorMask { Severity = 0x00F00000, // includes reserved bits, 16 possible severity levels Error = 0x000FFFFF, // error | namespace Namespace = 0x000FF000, // 256 possible namespaces - BaseError = 0x00000FFF, // error code, 2,048 possible error codes per namespace + BaseError = 0x00000FFF, // error code, 4,096 possible error codes per namespace Reserved = 0xFF000000, // do not use these error values at this time }; diff --git a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts index 88a2a9dbd1..c90c80c4a6 100644 --- a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts +++ b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts @@ -1,6 +1,6 @@ import { KeyAddress } from "../kmw-compiler/compile-layout-file.js"; import { kmnfile } from "../kmw-compiler/compiler-globals.js"; -import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec as m, CompilerMessageObjectSpec as mx, CompilerMessageDef as def, CompilerMessageSpecWithException, KeymanUrls } from "@keymanapp/developer-utils"; +import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerMessageSpec, CompilerMessageObjectSpec, CompilerMessageDef as def, CompilerMessageSpecWithException, KeymanUrls } from "@keymanapp/developer-utils"; import { ObjectWithCompileContext } from "@keymanapp/common-types"; const Namespace = CompilerErrorNamespace.KmnCompiler; const SevInfo = CompilerErrorSeverity.Info | Namespace; @@ -9,18 +9,58 @@ const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; const SevFatal = CompilerErrorSeverity.Fatal | Namespace; +// Because we have several overlapping components generating messages here, we +// wrap the message generation functions with a source property, in order to +// verify that we use the correct pattern as far as possible + // For messages from the KeymanWeb compiler, we need to construct our messages // slightly differently. This could be refactored in the future, as it is not // obvious which messages should use which function. // Specifically, this could perhaps use CompilerFileCallbacks which provides a // default filename. // Then, there could be a CompilerMessageSpecWithLine -const mw = (code: number, message: string, o?: {filename?: string, line?: number}) : CompilerEvent => ({ - ...m(code, message), + +// messages from kmw compiler component (mw) + +export type KmcKmnMessageSource = 'kmw-compiler' | 'kmcmplib' | 'kmc-kmn'; + +export interface KmcKmnCompilerEvent extends CompilerEvent { + kmcKmnSource: KmcKmnMessageSource; +} + +const mw = (code: number, message: string, o?: {filename?: string, line?: number}) : KmcKmnCompilerEvent => ({ + ...CompilerMessageSpec(code, message), filename: o?.filename ?? kmnfile, line: o?.line, + kmcKmnSource: "kmw-compiler", }); +// messages from kmcmplib component (mc) + +const mc = (code: number, message: string, detail?: string) : KmcKmnCompilerEvent => ({ + ...CompilerMessageSpec(code, message, detail), + kmcKmnSource: "kmcmplib", +}); + +// messages from kmc-kmn component (m, mx) + +const m = (code: number, message: string, detail?: string) : KmcKmnCompilerEvent => ({ + ...CompilerMessageSpec(code, message, detail), + kmcKmnSource: "kmc-kmn", +}); + +const mx = (code: number, context: ObjectWithCompileContext, message: string, detail?: string) : KmcKmnCompilerEvent => ({ + ...CompilerMessageObjectSpec(code, context, message, detail), + kmcKmnSource: "kmc-kmn", +}); + +const kmcKmnCompilerMessageSpecWithException = (code: number, message: string, exceptionVar: any, detail?: string): KmcKmnCompilerEvent => ({ + ...CompilerMessageSpecWithException(code, message, exceptionVar, detail), + kmcKmnSource: "kmc-kmn", +}); + +// + export const enum KmnCompilerMessageRanges { RANGE_KMN_COMPILER_MIN = 0x001, // from kmn_compiler_errors.h RANGE_KMN_COMPILER_MAX = 0x7FF, // from kmn_compiler_errors.h @@ -41,7 +81,7 @@ export function keyAddress(address: KeyAddress): string { ''))); } -type KmcmpLibMessageParameters = {p:string[]}; +export type KmcmpLibMessageParameters = {p:string[]}; /** * @internal @@ -49,31 +89,33 @@ type KmcmpLibMessageParameters = {p:string[]}; * Error messages reported by the .kmn compiler. The error codes in this class * share an address space with messages from kmn_compiler_errors.h, which are * generated by kmcmplib, so codes below 0x900 are reserved for kmcmplib - * messages. + * messages. These messages should use `m()`, `mx()`, or + * `kmcKmnCompilerMessageSpecWithException()` calls. * - * The second half of this class defines the messages from kmcmplib. These - * messages should correspond to codes in kmn_compiler_errors.h, exclusive - * severity bits. Message text is defined by kmcmplib and passed through a - * callback at this time. The message text presented here is currently unused - * during the compilation process, but is used in the `kmc messages` tool and - * for documentation. + * The second half of this class defines messages from kmcmplib or the kmw + * compiler. For historical reasons, these messages are not in separate numeric + * ranges. These messages should correspond to codes in kmn_compiler_errors.h, + * exclusive severity bits. For messages generated by kmcmplib, any parameters + * must use the KmcmpLibMessageParameters type, not named parameters. kmcmplib + * messages must use `mc()` and kmw compiler messages must use `mw()` calls. * * `CERR_` messages that are actually fatals have been renamed to `FATAL_`. * * @example * - * ``` - * kmcmplib.CERR_BadCallParams = CERR_FATAL | 0x002 = 0x8002 - * ERROR_BadCallParams = SevError | 0x0002 = 0x300000 | 0x2000 | 0x002 = 0x302002 - * ``` + *``` + * kmcmplib.CERR_BadCallParams = CERR_FATAL | 0x002 = 0x8002 + * ERROR_BadCallParams = SevError | 0x0002 = 0x300000 | 0x2000 | 0x002 = 0x302002 + *``` */ export class KmnCompilerMessages { - // TODO: v18.0 we should consider moving error message generation in kmcmplib to - // kmc-kmn, which would avoid a number of legacy issues. Questions about - // parameterisation. + + // ------------------------------------------------------------------------------------------------ + // kmc-kmn compiler messages - 0x900-0xFFF (RANGE_CompilerMessage_Min..RANGE_CompilerMessage_Max) + // ------------------------------------------------------------------------------------------------ static FATAL_UnexpectedException = SevFatal | 0x900; - static Fatal_UnexpectedException = (o:{e: any}) => CompilerMessageSpecWithException( + static Fatal_UnexpectedException = (o:{e: any}) => kmcKmnCompilerMessageSpecWithException( this.FATAL_UnexpectedException, null, o.e ?? 'unknown error', @@ -83,7 +125,7 @@ export class KmnCompilerMessages { ); static FATAL_MissingWasmModule = SevFatal | 0x901; - static Fatal_MissingWasmModule = (o:{e?: any}) => CompilerMessageSpecWithException( + static Fatal_MissingWasmModule = (o:{e?: any}) => kmcKmnCompilerMessageSpecWithException( this.FATAL_MissingWasmModule, `Could not instantiate WASM compiler module or initialization failed`, o.e ?? 'unknown error', @@ -97,7 +139,7 @@ export class KmnCompilerMessages { // static Fatal_UnableToSetCompilerOptions = () => m(this.FATAL_UnableToSetCompilerOptions, null, `Unable to set compiler options`); static FATAL_CallbacksNotSet = SevFatal | 0x903; - static Fatal_CallbacksNotSet = () => CompilerMessageSpecWithException( + static Fatal_CallbacksNotSet = () => kmcKmnCompilerMessageSpecWithException( this.FATAL_CallbacksNotSet, null, `Callbacks were not set with init`, @@ -202,560 +244,607 @@ export class KmnCompilerMessages { to the file.` ); + // + // ------------------------------------------------------------------------------------------------ + // kmcmplib messages - 0x000-0x8FF + // + // All parameters must be KmcmpLibMessageParameters type + // ------------------------------------------------------------------------------------------------ + // + // static STATUS_None = 0x000; // This is not a real error // static STATUS_EndOfFile = 0x001; // This is not a real error static FATAL_BadCallParams = SevFatal | 0x002; - static Fatal_BadCallParams = () => m(this.FATAL_BadCallParams, `CompileKeyboardFile was called with bad parameters`); + static Fatal_BadCallParams = () => mc(this.FATAL_BadCallParams, `CompileKeyboardFile was called with bad parameters`); static FATAL_CannotAllocateMemory = SevFatal | 0x004; - static Fatal_CannotAllocateMemory = () => m(this.FATAL_CannotAllocateMemory, `Out of memory`); + static Fatal_CannotAllocateMemory = () => mc(this.FATAL_CannotAllocateMemory, `Out of memory`); static ERROR_InfileNotExist = SevError | 0x005; // #10678: reduced from fatal to error in 17.0 - static Error_InfileNotExist = () => m(this.ERROR_InfileNotExist, `Cannot find the input file`); + static Error_InfileNotExist = () => mc(this.ERROR_InfileNotExist, `Cannot find the input file`); // static ERROR_CannotCreateOutfile = SevError | 0x006; // #10678: reduced from fatal to error in 17.0, but unused - // static Error_CannotCreateOutfile = () => m(this.ERROR_CannotCreateOutfile, `Cannot open output file for writing`); unused + // static Error_CannotCreateOutfile = () => mc(this.ERROR_CannotCreateOutfile, `Cannot open output file for writing`); unused // static FATAL_UnableToWriteFully = SevFatal | 0x007; - // static Fatal_UnableToWriteFully = () => m(this.FATAL_UnableToWriteFully, `Unable to write the file completely`); + // static Fatal_UnableToWriteFully = () => mc(this.FATAL_UnableToWriteFully, `Unable to write the file completely`); static ERROR_CannotReadInfile = SevError | 0x008; // #10678: reduced from fatal to error in 17.0 - static Error_CannotReadInfile = () => m(this.ERROR_CannotReadInfile, `Cannot read the input file`); + static Error_CannotReadInfile = () => mc(this.ERROR_CannotReadInfile, `Cannot read the input file`); static FATAL_SomewhereIGotItWrong = SevFatal | 0x009; - static Fatal_SomewhereIGotItWrong = () => m(this.FATAL_SomewhereIGotItWrong, `Internal error: contact Keyman`); + static Fatal_SomewhereIGotItWrong = () => mc(this.FATAL_SomewhereIGotItWrong, `Internal error: contact Keyman`); static ERROR_InvalidToken = SevError | 0x00A; - static Error_InvalidToken = () => m(this.ERROR_InvalidToken, `Invalid token found`); + static Error_InvalidToken = () => mc(this.ERROR_InvalidToken, `Invalid token found`); - // kmcmplib: static Error_InvalidBegin = () => m(this.ERROR_InvalidBegin, `Invalid 'begin' statement`); static ERROR_InvalidBegin = SevError | 0x00B; - static Error_InvalidBegin = () => mw(this.ERROR_InvalidBegin, - `A "begin unicode" statement is required to compile a KeymanWeb keyboard`); + static Error_InvalidBegin = () => mc( + this.ERROR_InvalidBegin, + `A "begin unicode" statement is required to compile a KeymanWeb keyboard`, + ); static ERROR_InvalidName = SevError | 0x00C; - static Error_InvalidName = () => m(this.ERROR_InvalidName, `Invalid 'name' statement`); + static Error_InvalidName = () => mc(this.ERROR_InvalidName, `Invalid 'name' statement`); static ERROR_InvalidVersion = SevError | 0x00D; - static Error_InvalidVersion = () => m(this.ERROR_InvalidVersion, `Invalid 'version' statement`); + static Error_InvalidVersion = () => mc(this.ERROR_InvalidVersion, `Invalid 'version' statement`); static ERROR_InvalidLanguageLine = SevError | 0x00E; - static Error_InvalidLanguageLine = () => m(this.ERROR_InvalidLanguageLine, `Invalid 'language' statement`); + static Error_InvalidLanguageLine = () => mc(this.ERROR_InvalidLanguageLine, `Invalid 'language' statement`); static ERROR_LayoutButNoLanguage = SevError | 0x00F; - static Error_LayoutButNoLanguage = () => m(this.ERROR_LayoutButNoLanguage, `Layout statement found but no language statement`); + static Error_LayoutButNoLanguage = () => mc(this.ERROR_LayoutButNoLanguage, `Layout statement found but no language statement`); static ERROR_InvalidLayoutLine = SevError | 0x010; - static Error_InvalidLayoutLine = () => m(this.ERROR_InvalidLayoutLine, `Invalid 'layout' statement`); + static Error_InvalidLayoutLine = () => mc(this.ERROR_InvalidLayoutLine, `Invalid 'layout' statement`); static ERROR_NoVersionLine = SevError | 0x011; - static Error_NoVersionLine = () => m(this.ERROR_NoVersionLine, `No version line found for file`); + static Error_NoVersionLine = () => mc(this.ERROR_NoVersionLine, `No version line found for file`); static ERROR_InvalidGroupLine = SevError | 0x012; - static Error_InvalidGroupLine = () => m(this.ERROR_InvalidGroupLine, `Invalid 'group' statement`); + static Error_InvalidGroupLine = () => mc(this.ERROR_InvalidGroupLine, `Invalid 'group' statement`); static ERROR_InvalidStoreLine = SevError | 0x013; - static Error_InvalidStoreLine = () => m(this.ERROR_InvalidStoreLine, `Invalid 'store' statement`); + static Error_InvalidStoreLine = () => mc(this.ERROR_InvalidStoreLine, `Invalid 'store' statement`); static ERROR_InvalidCodeInKeyPartOfRule = SevError | 0x014; - static Error_InvalidCodeInKeyPartOfRule = () => m(this.ERROR_InvalidCodeInKeyPartOfRule, `Invalid statement or code found in key part of rule`); + static Error_InvalidCodeInKeyPartOfRule = () => mc(this.ERROR_InvalidCodeInKeyPartOfRule, `Invalid statement or code found in key part of rule`); static ERROR_InvalidDeadkey = SevError | 0x015; - static Error_InvalidDeadkey = () => m(this.ERROR_InvalidDeadkey, `Invalid 'deadkey' or 'dk' statement`); + static Error_InvalidDeadkey = () => mc(this.ERROR_InvalidDeadkey, `Invalid 'deadkey' or 'dk' statement`); static ERROR_InvalidValue = SevError | 0x016; - static Error_InvalidValue = () => m(this.ERROR_InvalidValue, `Invalid value in extended string`); + static Error_InvalidValue = () => mc(this.ERROR_InvalidValue, `Invalid value in extended string`); static ERROR_ZeroLengthString = SevError | 0x017; - static Error_ZeroLengthString = () => m(this.ERROR_ZeroLengthString, `A string of zero characters was found`); + static Error_ZeroLengthString = () => mc(this.ERROR_ZeroLengthString, `A string of zero characters was found`); static ERROR_TooManyIndexToKeyRefs = SevError | 0x018; - static Error_TooManyIndexToKeyRefs = () => m(this.ERROR_TooManyIndexToKeyRefs, `Too many index statements refering to key string`); + static Error_TooManyIndexToKeyRefs = () => mc(this.ERROR_TooManyIndexToKeyRefs, `Too many index statements refering to key string`); static ERROR_UnterminatedString = SevError | 0x019; - static Error_UnterminatedString = () => m(this.ERROR_UnterminatedString, `Unterminated string in line`); + static Error_UnterminatedString = () => mc(this.ERROR_UnterminatedString, `Unterminated string in line`); // static ERROR_StringInVirtualKeySection = SevError | 0x01A; // no longer used, see #12612 - // static Error_StringInVirtualKeySection = () => m(this.ERROR_StringInVirtualKeySection, `extend string illegal in virtual key section`); + // static Error_StringInVirtualKeySection = () => mc(this.ERROR_StringInVirtualKeySection, `extend string illegal in virtual key section`); // static ERROR_AnyInVirtualKeySection = SevError | 0x01B; // no longer used, see #12612 - // static Error_AnyInVirtualKeySection = () => m(this.ERROR_AnyInVirtualKeySection, `'any' statement is illegal in virtual key section`); + // static Error_AnyInVirtualKeySection = () => mc(this.ERROR_AnyInVirtualKeySection, `'any' statement is illegal in virtual key section`); static ERROR_InvalidAny = SevError | 0x01C; - static Error_InvalidAny = () => m(this.ERROR_InvalidAny, `Invalid 'any' statement`); + static Error_InvalidAny = () => mc(this.ERROR_InvalidAny, `Invalid 'any' statement`); static ERROR_StoreDoesNotExist = SevError | 0x01D; - static Error_StoreDoesNotExist = () => m(this.ERROR_StoreDoesNotExist, `Store referenced does not exist`); + static Error_StoreDoesNotExist = () => mc(this.ERROR_StoreDoesNotExist, `Store referenced does not exist`); // static ERROR_BeepInVirtualKeySection = SevError | 0x01E; // no longer used, see #12612 - // static Error_BeepInVirtualKeySection = () => m(this.ERROR_BeepInVirtualKeySection, `'beep' statement is illegal in virtual key section`); + // static Error_BeepInVirtualKeySection = () => mc(this.ERROR_BeepInVirtualKeySection, `'beep' statement is illegal in virtual key section`); // static ERROR_IndexInVirtualKeySection = SevError | 0x01F; // no longer used, see #12612 - // static Error_IndexInVirtualKeySection = () => m(this.ERROR_IndexInVirtualKeySection, `'index' statement is illegal in virtual key section`); + // static Error_IndexInVirtualKeySection = () => mc(this.ERROR_IndexInVirtualKeySection, `'index' statement is illegal in virtual key section`); static ERROR_InvalidIndex = SevError | 0x020; - static Error_InvalidIndex = () => m(this.ERROR_InvalidIndex, `Invalid 'index' statement`); + static Error_InvalidIndex = () => mc(this.ERROR_InvalidIndex, `Invalid 'index' statement`); // static ERROR_OutsInVirtualKeySection = SevError | 0x021; // no longer used, see #12612 - // static Error_OutsInVirtualKeySection = () => m(this.ERROR_OutsInVirtualKeySection, `'outs' statement is illegal in virtual key section`); + // static Error_OutsInVirtualKeySection = () => mc(this.ERROR_OutsInVirtualKeySection, `'outs' statement is illegal in virtual key section`); static ERROR_InvalidOuts = SevError | 0x022; - static Error_InvalidOuts = () => m(this.ERROR_InvalidOuts, `Invalid 'outs' statement`); + static Error_InvalidOuts = () => mc(this.ERROR_InvalidOuts, `Invalid 'outs' statement`); // static ERROR_ContextInVirtualKeySection = SevError | 0x024; // no longer used, see #12612 - // static Error_ContextInVirtualKeySection = () => m(this.ERROR_ContextInVirtualKeySection, `'context' statement is illegal in virtual key section`); + // static Error_ContextInVirtualKeySection = () => mc(this.ERROR_ContextInVirtualKeySection, `'context' statement is illegal in virtual key section`); static ERROR_InvalidUse = SevError | 0x025; - static Error_InvalidUse = () => m(this.ERROR_InvalidUse, `Invalid 'use' statement`); + static Error_InvalidUse = () => mc(this.ERROR_InvalidUse, `Invalid 'use' statement`); static ERROR_GroupDoesNotExist = SevError | 0x026; - static Error_GroupDoesNotExist = () => m(this.ERROR_GroupDoesNotExist, `Group does not exist`); + static Error_GroupDoesNotExist = () => mc(this.ERROR_GroupDoesNotExist, `Group does not exist`); static ERROR_VirtualKeyNotAllowedHere = SevError | 0x027; - static Error_VirtualKeyNotAllowedHere = () => m(this.ERROR_VirtualKeyNotAllowedHere, `Virtual key is not allowed here`); + static Error_VirtualKeyNotAllowedHere = () => mc(this.ERROR_VirtualKeyNotAllowedHere, `Virtual key is not allowed here`); static ERROR_InvalidSwitch = SevError | 0x028; - static Error_InvalidSwitch = () => m(this.ERROR_InvalidSwitch, `Invalid 'switch' statement`); + static Error_InvalidSwitch = () => mc(this.ERROR_InvalidSwitch, `Invalid 'switch' statement`); static ERROR_NoTokensFound = SevError | 0x029; - static Error_NoTokensFound = () => m(this.ERROR_NoTokensFound, `No tokens found in line`); + static Error_NoTokensFound = () => mc(this.ERROR_NoTokensFound, `No tokens found in line`); static ERROR_InvalidLineContinuation = SevError | 0x02A; - static Error_InvalidLineContinuation = () => m(this.ERROR_InvalidLineContinuation, `Invalid line continuation`); + static Error_InvalidLineContinuation = () => mc(this.ERROR_InvalidLineContinuation, `Invalid line continuation`); static ERROR_LineTooLong = SevError | 0x02B; - static Error_LineTooLong = () => m(this.ERROR_LineTooLong, `Line too long`); + static Error_LineTooLong = () => mc(this.ERROR_LineTooLong, `Line too long`); static ERROR_InvalidCopyright = SevError | 0x02C; - static Error_InvalidCopyright = () => m(this.ERROR_InvalidCopyright, `Invalid 'copyright' statement`); + static Error_InvalidCopyright = () => mc(this.ERROR_InvalidCopyright, `Invalid 'copyright' statement`); static ERROR_CodeInvalidInThisSection = SevError | 0x02D; - static Error_CodeInvalidInThisSection = () => m(this.ERROR_CodeInvalidInThisSection, `This line is invalid in this section of the file`); + static Error_CodeInvalidInThisSection = () => mc(this.ERROR_CodeInvalidInThisSection, `This line is invalid in this section of the file`); static ERROR_InvalidMessage = SevError | 0x02E; - static Error_InvalidMessage = () => m(this.ERROR_InvalidMessage, `Invalid 'message' statement`); + static Error_InvalidMessage = () => mc(this.ERROR_InvalidMessage, `Invalid 'message' statement`); static ERROR_InvalidLanguageName = SevError | 0x02F; - static Error_InvalidLanguageName = () => m(this.ERROR_InvalidLanguageName, `Invalid 'languagename' statement`); + static Error_InvalidLanguageName = () => mc(this.ERROR_InvalidLanguageName, `Invalid 'languagename' statement`); static ERROR_InvalidBitmapLine = SevError | 0x030; - static Error_InvalidBitmapLine = () => m(this.ERROR_InvalidBitmapLine, `Invalid 'bitmaps' statement`); + static Error_InvalidBitmapLine = () => mc(this.ERROR_InvalidBitmapLine, `Invalid 'bitmaps' statement`); static ERROR_CannotReadBitmapFile = SevError | 0x031; - static Error_CannotReadBitmapFile = () => m(this.ERROR_CannotReadBitmapFile, `Cannot open the bitmap or icon file for reading`); + static Error_CannotReadBitmapFile = () => mc(this.ERROR_CannotReadBitmapFile, `Cannot open the bitmap or icon file for reading`); static ERROR_IndexDoesNotPointToAny = SevError | 0x032; - static Error_IndexDoesNotPointToAny = () => m(this.ERROR_IndexDoesNotPointToAny, `An index() in the output does not have a corresponding any() statement`); + static Error_IndexDoesNotPointToAny = () => mc(this.ERROR_IndexDoesNotPointToAny, `An index() in the output does not have a corresponding any() statement`); static ERROR_ReservedCharacter = SevError | 0x033; - static Error_ReservedCharacter = () => m(this.ERROR_ReservedCharacter, `A reserved character was found`); + static Error_ReservedCharacter = () => mc(this.ERROR_ReservedCharacter, `A reserved character was found`); static ERROR_InvalidCharacter = SevError | 0x034; - static Error_InvalidCharacter = () => m(this.ERROR_InvalidCharacter, `A character was found that is outside the valid Unicode range (U+0000 - U+10FFFF)`); + static Error_InvalidCharacter = () => mc(this.ERROR_InvalidCharacter, `A character was found that is outside the valid Unicode range (U+0000 - U+10FFFF)`); static ERROR_InvalidCall = SevError | 0x035; - static Error_InvalidCall = () => m(this.ERROR_InvalidCall, `The 'call' statement is invalid`); + static Error_InvalidCall = () => mc(this.ERROR_InvalidCall, `The 'call' statement is invalid`); // static ERROR_CallInVirtualKeySection = SevError | 0x036; // no longer used, see #12612 - // static Error_CallInVirtualKeySection = () => m(this.ERROR_CallInVirtualKeySection, `'call' statement is illegal in virtual key section`); + // static Error_CallInVirtualKeySection = () => mc(this.ERROR_CallInVirtualKeySection, `'call' statement is illegal in virtual key section`); static ERROR_CodeInvalidInKeyStore = SevError | 0x037; - static Error_CodeInvalidInKeyStore = () => m(this.ERROR_CodeInvalidInKeyStore, `The statement is invalid inside a store that is used in a key part of the rule`); + static Error_CodeInvalidInKeyStore = () => mc(this.ERROR_CodeInvalidInKeyStore, `The statement is invalid inside a store that is used in a key part of the rule`); static ERROR_CannotLoadIncludeFile = SevError | 0x038; - static Error_CannotLoadIncludeFile = () => m(this.ERROR_CannotLoadIncludeFile, `Cannot load the included file: it is either invalid or does not exist`); + static Error_CannotLoadIncludeFile = () => mc(this.ERROR_CannotLoadIncludeFile, `Cannot load the included file: it is either invalid or does not exist`); static ERROR_60FeatureOnly_EthnologueCode = SevError | 0x039; - static Error_60FeatureOnly_EthnologueCode = () => m(this.ERROR_60FeatureOnly_EthnologueCode, `EthnologueCode system store requires VERSION 6.0 or higher`); + static Error_60FeatureOnly_EthnologueCode = () => mc(this.ERROR_60FeatureOnly_EthnologueCode, `EthnologueCode system store requires VERSION 6.0 or higher`); static ERROR_60FeatureOnly_MnemonicLayout = SevError | 0x03A; - static Error_60FeatureOnly_MnemonicLayout = () => m(this.ERROR_60FeatureOnly_MnemonicLayout, `MnemonicLayout functionality requires VERSION 6.0 or higher`); + static Error_60FeatureOnly_MnemonicLayout = () => mc(this.ERROR_60FeatureOnly_MnemonicLayout, `MnemonicLayout functionality requires VERSION 6.0 or higher`); static ERROR_60FeatureOnly_OldCharPosMatching = SevError | 0x03B; - static Error_60FeatureOnly_OldCharPosMatching = () => m(this.ERROR_60FeatureOnly_OldCharPosMatching, `OldCharPosMatching system store requires VERSION 6.0 or higher`); + static Error_60FeatureOnly_OldCharPosMatching = () => mc(this.ERROR_60FeatureOnly_OldCharPosMatching, `OldCharPosMatching system store requires VERSION 6.0 or higher`); static ERROR_60FeatureOnly_NamedCodes = SevError | 0x03C; - static Error_60FeatureOnly_NamedCodes = () => m(this.ERROR_60FeatureOnly_NamedCodes, `Named character constants requires VERSION 6.0 or higher`); + static Error_60FeatureOnly_NamedCodes = () => mc(this.ERROR_60FeatureOnly_NamedCodes, `Named character constants requires VERSION 6.0 or higher`); static ERROR_60FeatureOnly_Contextn = SevError | 0x03D; - static Error_60FeatureOnly_Contextn = () => m(this.ERROR_60FeatureOnly_Contextn, `Context(n) requires VERSION 6.0 or higher`); + static Error_60FeatureOnly_Contextn = () => mc(this.ERROR_60FeatureOnly_Contextn, `Context(n) requires VERSION 6.0 or higher`); static ERROR_501FeatureOnly_Call = SevError | 0x03E; - static Error_501FeatureOnly_Call = () => m(this.ERROR_501FeatureOnly_Call, `Call() requires VERSION 5.01 or higher`); + static Error_501FeatureOnly_Call = () => mc(this.ERROR_501FeatureOnly_Call, `Call() requires VERSION 5.01 or higher`); static ERROR_InvalidNamedCode = SevError | 0x03F; - static Error_InvalidNamedCode = () => m(this.ERROR_InvalidNamedCode, `Invalid named code constant`); + static Error_InvalidNamedCode = () => mc(this.ERROR_InvalidNamedCode, `Invalid named code constant`); static ERROR_InvalidSystemStore = SevError | 0x040; - static Error_InvalidSystemStore = () => m(this.ERROR_InvalidSystemStore, `Invalid system store name found`); + static Error_InvalidSystemStore = () => mc(this.ERROR_InvalidSystemStore, `Invalid system store name found`); static ERROR_60FeatureOnly_VirtualCharKey = SevError | 0x044; - static Error_60FeatureOnly_VirtualCharKey = () => m(this.ERROR_60FeatureOnly_VirtualCharKey, `Virtual character keys require VERSION 6.0 or higher`); + static Error_60FeatureOnly_VirtualCharKey = () => mc(this.ERROR_60FeatureOnly_VirtualCharKey, `Virtual character keys require VERSION 6.0 or higher`); static ERROR_VersionAlreadyIncluded = SevError | 0x045; - static Error_VersionAlreadyIncluded = () => m(this.ERROR_VersionAlreadyIncluded, `Only one VERSION or store(version) line allowed in a source file.`); + static Error_VersionAlreadyIncluded = () => mc(this.ERROR_VersionAlreadyIncluded, `Only one VERSION or store(version) line allowed in a source file.`); static ERROR_70FeatureOnly = SevError | 0x046; - static Error_70FeatureOnly = () => m(this.ERROR_70FeatureOnly, `This feature requires store(version) '7.0' or higher`); + static Error_70FeatureOnly = () => mc(this.ERROR_70FeatureOnly, `This feature requires store(version) '7.0' or higher`); static ERROR_80FeatureOnly = SevError | 0x047; - static Error_80FeatureOnly = () => m(this.ERROR_80FeatureOnly, `This feature requires store(version) '8.0' or higher`); + static Error_80FeatureOnly = () => mc(this.ERROR_80FeatureOnly, `This feature requires store(version) '8.0' or higher`); // static ERROR_InvalidInVirtualKeySection = SevError | 0x048; // no longer used, see #12612 - // static Error_InvalidInVirtualKeySection = () => m(this.ERROR_InvalidInVirtualKeySection, `This statement is not valid in a virtual key section`); + // static Error_InvalidInVirtualKeySection = () => mc(this.ERROR_InvalidInVirtualKeySection, `This statement is not valid in a virtual key section`); static ERROR_InvalidIf = SevError | 0x049; - static Error_InvalidIf = () => m(this.ERROR_InvalidIf, `The if() statement is not valid`); + static Error_InvalidIf = () => mc(this.ERROR_InvalidIf, `The if() statement is not valid`); static ERROR_InvalidReset = SevError | 0x04A; - static Error_InvalidReset = () => m(this.ERROR_InvalidReset, `The reset() statement is not valid`); + static Error_InvalidReset = () => mc(this.ERROR_InvalidReset, `The reset() statement is not valid`); static ERROR_InvalidSet = SevError | 0x04B; - static Error_InvalidSet = () => m(this.ERROR_InvalidSet, `The set() statement is not valid`); + static Error_InvalidSet = () => mc(this.ERROR_InvalidSet, `The set() statement is not valid`); static ERROR_InvalidSave = SevError | 0x04C; - static Error_InvalidSave = () => m(this.ERROR_InvalidSave, `The save() statement is not valid`); + static Error_InvalidSave = () => mc(this.ERROR_InvalidSave, `The save() statement is not valid`); static ERROR_InvalidEthnologueCode = SevError | 0x04D; - static Error_InvalidEthnologueCode = () => m(this.ERROR_InvalidEthnologueCode, `Invalid ethnologuecode format`); + static Error_InvalidEthnologueCode = () => mc(this.ERROR_InvalidEthnologueCode, `Invalid ethnologuecode format`); static FATAL_CannotCreateTempfile = SevFatal | 0x04E; - static Fatal_CannotCreateTempfile = () => m(this.FATAL_CannotCreateTempfile, `Cannot create temp file`); + static Fatal_CannotCreateTempfile = () => mc(this.FATAL_CannotCreateTempfile, `Cannot create temp file`); static ERROR_90FeatureOnly_IfSystemStores = SevError | 0x04F; - static Error_90FeatureOnly_IfSystemStores = () => m(this.ERROR_90FeatureOnly_IfSystemStores, `if(store) requires store(version) '9.0' or higher`); + static Error_90FeatureOnly_IfSystemStores = () => mc(this.ERROR_90FeatureOnly_IfSystemStores, `if(store) requires store(version) '9.0' or higher`); static ERROR_IfSystemStore_NotFound = SevError | 0x050; - static Error_IfSystemStore_NotFound = () => m(this.ERROR_IfSystemStore_NotFound, `System store in if() not found`); + static Error_IfSystemStore_NotFound = () => mc(this.ERROR_IfSystemStore_NotFound, `System store in if() not found`); static ERROR_90FeatureOnly_SetSystemStores = SevError | 0x051; - static Error_90FeatureOnly_SetSystemStores = () => m(this.ERROR_90FeatureOnly_SetSystemStores, `set(store) requires store(version) '9.0' or higher`); + static Error_90FeatureOnly_SetSystemStores = () => mc(this.ERROR_90FeatureOnly_SetSystemStores, `set(store) requires store(version) '9.0' or higher`); static ERROR_SetSystemStore_NotFound = SevError | 0x052; - static Error_SetSystemStore_NotFound = () => m(this.ERROR_SetSystemStore_NotFound, `System store in set() not found`); + static Error_SetSystemStore_NotFound = () => mc(this.ERROR_SetSystemStore_NotFound, `System store in set() not found`); static ERROR_90FeatureOnlyVirtualKeyDictionary = SevError | 0x053; - static Error_90FeatureOnlyVirtualKeyDictionary = () => m(this.ERROR_90FeatureOnlyVirtualKeyDictionary, `Custom virtual key names require store(version) '9.0'`); + static Error_90FeatureOnlyVirtualKeyDictionary = () => mc(this.ERROR_90FeatureOnlyVirtualKeyDictionary, `Custom virtual key names require store(version) '9.0'`); static ERROR_NotSupportedInKeymanWebContext = SevError | 0x054; - static Error_NotSupportedInKeymanWebContext = (o:{line:number, code:String}) => mw(this.ERROR_NotSupportedInKeymanWebContext, - `Statement '${def(o.code)}' is not currently supported in context for web and touch targets`, o); + static Error_NotSupportedInKeymanWebContext = (o:{line:number, code:String}) => mw( + this.ERROR_NotSupportedInKeymanWebContext, + `Statement '${def(o.code)}' is not currently supported in context for web and touch targets`, o, + ); static ERROR_NotSupportedInKeymanWebOutput = SevError | 0x055; - static Error_NotSupportedInKeymanWebOutput = (o:{line:number, code:string}) => mw(this.ERROR_NotSupportedInKeymanWebOutput, - `Statement '${def(o.code)}' is not currently supported in output for web and touch targets`, o); + static Error_NotSupportedInKeymanWebOutput = (o:{line:number, code:string}) => mw( + this.ERROR_NotSupportedInKeymanWebOutput, + `Statement '${def(o.code)}' is not currently supported in output for web and touch targets`, o, + ); static ERROR_NotSupportedInKeymanWebStore = SevError | 0x056; - static Error_NotSupportedInKeymanWebStore = (o:{code:string,store:string}) => mw(this.ERROR_NotSupportedInKeymanWebStore, - `'${def(o.code)}' is not currently supported in store '${def(o.store)}' when used by any or index for web and touch targets`); + static Error_NotSupportedInKeymanWebStore = (o:{code:string,store:string}) => mw( + this.ERROR_NotSupportedInKeymanWebStore, + `'${def(o.code)}' is not currently supported in store '${def(o.store)}' when used by any or index for web and touch targets`, + ); static ERROR_VirtualCharacterKeysNotSupportedInKeymanWeb = SevError | 0x057; - static Error_VirtualCharacterKeysNotSupportedInKeymanWeb = (o:{line:number}) => mw(this.ERROR_VirtualCharacterKeysNotSupportedInKeymanWeb, - `Virtual character keys not currently supported in KeymanWeb`, o); + static Error_VirtualCharacterKeysNotSupportedInKeymanWeb = (o:{line:number}) => mw( + this.ERROR_VirtualCharacterKeysNotSupportedInKeymanWeb, + `Virtual character keys not currently supported in KeymanWeb`, o, + ); static ERROR_VirtualKeysNotValidForMnemonicLayouts = SevError | 0x058; - static Error_VirtualKeysNotValidForMnemonicLayouts = (o:{line:number}) => mw(this.ERROR_VirtualKeysNotValidForMnemonicLayouts, - `Virtual keys are not valid for mnemonic layouts`, o); + static Error_VirtualKeysNotValidForMnemonicLayouts = (o:{line:number}) => mw( + this.ERROR_VirtualKeysNotValidForMnemonicLayouts, + `Virtual keys are not valid for mnemonic layouts`, o, + ); static ERROR_InvalidTouchLayoutFile = SevError | 0x059; - static Error_InvalidTouchLayoutFile = (o:{filename:string}) => mw(this.ERROR_InvalidTouchLayoutFile, - `Touch layout file ${def(o.filename)} is not valid`); + static Error_InvalidTouchLayoutFile = (o:{filename:string}) => mw( + this.ERROR_InvalidTouchLayoutFile, + `Touch layout file ${def(o.filename)} is not valid`, + ); static ERROR_TouchLayoutInvalidIdentifier = SevError | 0x05A; - static Error_TouchLayoutInvalidIdentifier = (o:{keyId:string, platformName: string, layerId:string, address:KeyAddress}) => mw(this.ERROR_TouchLayoutInvalidIdentifier, - `Key "${def(o.keyId)}" on "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}) has an invalid identifier.`); + static Error_TouchLayoutInvalidIdentifier = (o:{keyId:string, platformName: string, layerId:string, address:KeyAddress}) => mw( + this.ERROR_TouchLayoutInvalidIdentifier, + `Key "${def(o.keyId)}" on "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}) has an invalid identifier.`, + ); static ERROR_InvalidKeyCode = SevError | 0x05B; - static Error_InvalidKeyCode = (o:{keyId: string}) => mw(this.ERROR_InvalidKeyCode, - `Invalid key identifier "${def(o.keyId)}"`); + static Error_InvalidKeyCode = (o:{keyId: string}) => mw(this.ERROR_InvalidKeyCode, + `Invalid key identifier "${def(o.keyId)}"`, + ); static ERROR_90FeatureOnlyLayoutFile = SevError | 0x05C; - static Error_90FeatureOnlyLayoutFile = () => m(this.ERROR_90FeatureOnlyLayoutFile, `Touch layout file reference requires store(version) '9.0' or higher`); + static Error_90FeatureOnlyLayoutFile = () => mc(this.ERROR_90FeatureOnlyLayoutFile, `Touch layout file reference requires store(version) '9.0' or higher`); static ERROR_90FeatureOnlyKeyboardVersion = SevError | 0x05D; - static Error_90FeatureOnlyKeyboardVersion = () => m(this.ERROR_90FeatureOnlyKeyboardVersion, `KeyboardVersion system store requires store(version) '9.0' or higher`); + static Error_90FeatureOnlyKeyboardVersion = () => mc(this.ERROR_90FeatureOnlyKeyboardVersion, `KeyboardVersion system store requires store(version) '9.0' or higher`); static ERROR_KeyboardVersionFormatInvalid = SevError | 0x05E; - static Error_KeyboardVersionFormatInvalid = () => m(this.ERROR_KeyboardVersionFormatInvalid, `KeyboardVersion format is invalid, expecting dot-separated integers`); + static Error_KeyboardVersionFormatInvalid = () => mc(this.ERROR_KeyboardVersionFormatInvalid, `KeyboardVersion format is invalid, expecting dot-separated integers`); static ERROR_ContextExHasInvalidOffset = SevError | 0x05F; - static Error_ContextExHasInvalidOffset = () => m(this.ERROR_ContextExHasInvalidOffset, `context() statement has offset out of range`); + static Error_ContextExHasInvalidOffset = () => mc(this.ERROR_ContextExHasInvalidOffset, `context() statement has offset out of range`); static ERROR_90FeatureOnlyEmbedCSS = SevError | 0x060; - static Error_90FeatureOnlyEmbedCSS = () => m(this.ERROR_90FeatureOnlyEmbedCSS, `Embedding CSS requires store(version) '9.0' or higher`); + static Error_90FeatureOnlyEmbedCSS = () => mc(this.ERROR_90FeatureOnlyEmbedCSS, `Embedding CSS requires store(version) '9.0' or higher`); static ERROR_90FeatureOnlyTargets = SevError | 0x061; - static Error_90FeatureOnlyTargets = () => m(this.ERROR_90FeatureOnlyTargets, `TARGETS system store requires store(version) '9.0' or higher`); + static Error_90FeatureOnlyTargets = () => mc(this.ERROR_90FeatureOnlyTargets, `TARGETS system store requires store(version) '9.0' or higher`); static ERROR_ContextAndIndexInvalidInMatchNomatch = SevError | 0x062; - static Error_ContextAndIndexInvalidInMatchNomatch = () => m(this.ERROR_ContextAndIndexInvalidInMatchNomatch, `context and index statements cannot be used in a match or nomatch statement`); + static Error_ContextAndIndexInvalidInMatchNomatch = () => mc(this.ERROR_ContextAndIndexInvalidInMatchNomatch, `context and index statements cannot be used in a match or nomatch statement`); static ERROR_140FeatureOnlyContextAndNotAnyWeb = SevError | 0x063; - static Error_140FeatureOnlyContextAndNotAnyWeb = () => m(this.ERROR_140FeatureOnlyContextAndNotAnyWeb, `For web and touch platforms, context() statement referring to notany() requires store(version) '14.0' or higher`); + static Error_140FeatureOnlyContextAndNotAnyWeb = () => mc(this.ERROR_140FeatureOnlyContextAndNotAnyWeb, `For web and touch platforms, context() statement referring to notany() requires store(version) '14.0' or higher`); static ERROR_ExpansionMustFollowCharacterOrVKey = SevError | 0x064; - static Error_ExpansionMustFollowCharacterOrVKey = () => m(this.ERROR_ExpansionMustFollowCharacterOrVKey, `An expansion must follow a character or a virtual key`); + static Error_ExpansionMustFollowCharacterOrVKey = () => mc(this.ERROR_ExpansionMustFollowCharacterOrVKey, `An expansion must follow a character or a virtual key`); static ERROR_VKeyExpansionMustBeFollowedByVKey = SevError | 0x065; - static Error_VKeyExpansionMustBeFollowedByVKey = () => m(this.ERROR_VKeyExpansionMustBeFollowedByVKey, `A virtual key expansion must be terminated by a virtual key`); + static Error_VKeyExpansionMustBeFollowedByVKey = () => mc(this.ERROR_VKeyExpansionMustBeFollowedByVKey, `A virtual key expansion must be terminated by a virtual key`); static ERROR_CharacterExpansionMustBeFollowedByCharacter = SevError | 0x066; - static Error_CharacterExpansionMustBeFollowedByCharacter = () => m(this.ERROR_CharacterExpansionMustBeFollowedByCharacter, `A character expansion must be terminated by a character key`); + static Error_CharacterExpansionMustBeFollowedByCharacter = () => mc(this.ERROR_CharacterExpansionMustBeFollowedByCharacter, `A character expansion must be terminated by a character key`); static ERROR_VKeyExpansionMustUseConsistentShift = SevError | 0x067; - static Error_VKeyExpansionMustUseConsistentShift = () => m(this.ERROR_VKeyExpansionMustUseConsistentShift, `A virtual key expansion must use the same shift state for both terminators`); + static Error_VKeyExpansionMustUseConsistentShift = () => mc(this.ERROR_VKeyExpansionMustUseConsistentShift, `A virtual key expansion must use the same shift state for both terminators`); static ERROR_ExpansionMustBePositive = SevError | 0x068; - static Error_ExpansionMustBePositive = () => m(this.ERROR_ExpansionMustBePositive, `An expansion must have positive difference (i.e. A-Z, not Z-A)`); + static Error_ExpansionMustBePositive = () => mc(this.ERROR_ExpansionMustBePositive, `An expansion must have positive difference (i.e. A-Z, not Z-A)`); static ERROR_CasedKeysMustContainOnlyVirtualKeys = SevError | 0x069; - static Error_CasedKeysMustContainOnlyVirtualKeys = () => m(this.ERROR_CasedKeysMustContainOnlyVirtualKeys, `The &CasedKeys system store must contain only virtual keys or characters found on a US English keyboard`); + static Error_CasedKeysMustContainOnlyVirtualKeys = () => mc(this.ERROR_CasedKeysMustContainOnlyVirtualKeys, `The &CasedKeys system store must contain only virtual keys or characters found on a US English keyboard`); static ERROR_CasedKeysMustNotIncludeShiftStates = SevError | 0x06A; - static Error_CasedKeysMustNotIncludeShiftStates = () => m(this.ERROR_CasedKeysMustNotIncludeShiftStates, `The &CasedKeys system store must not include shift states`); + static Error_CasedKeysMustNotIncludeShiftStates = () => mc(this.ERROR_CasedKeysMustNotIncludeShiftStates, `The &CasedKeys system store must not include shift states`); static ERROR_CasedKeysNotSupportedWithMnemonicLayout = SevError | 0x06B; - static Error_CasedKeysNotSupportedWithMnemonicLayout = () => m(this.ERROR_CasedKeysNotSupportedWithMnemonicLayout, `The &CasedKeys system store is not supported with mnemonic layouts`); + static Error_CasedKeysNotSupportedWithMnemonicLayout = () => mc(this.ERROR_CasedKeysNotSupportedWithMnemonicLayout, `The &CasedKeys system store is not supported with mnemonic layouts`); static ERROR_CannotUseReadWriteGroupFromReadonlyGroup = SevError | 0x06C; - static Error_CannotUseReadWriteGroupFromReadonlyGroup = () => m(this.ERROR_CannotUseReadWriteGroupFromReadonlyGroup, `Group used from a readonly group must also be readonly`); + static Error_CannotUseReadWriteGroupFromReadonlyGroup = () => mc(this.ERROR_CannotUseReadWriteGroupFromReadonlyGroup, `Group used from a readonly group must also be readonly`); static ERROR_StatementNotPermittedInReadonlyGroup = SevError | 0x06D; - static Error_StatementNotPermittedInReadonlyGroup = () => m(this.ERROR_StatementNotPermittedInReadonlyGroup, `Statement is not permitted in output of readonly group`); + static Error_StatementNotPermittedInReadonlyGroup = () => mc(this.ERROR_StatementNotPermittedInReadonlyGroup, `Statement is not permitted in output of readonly group`); static ERROR_OutputInReadonlyGroup = SevError | 0x06E; - static Error_OutputInReadonlyGroup = () => m(this.ERROR_OutputInReadonlyGroup, `Output is not permitted in a readonly group`); + static Error_OutputInReadonlyGroup = () => mc(this.ERROR_OutputInReadonlyGroup, `Output is not permitted in a readonly group`); static ERROR_NewContextGroupMustBeReadonly = SevError | 0x06F; - static Error_NewContextGroupMustBeReadonly = () => m(this.ERROR_NewContextGroupMustBeReadonly, `Group used in begin newContext must be readonly`); + static Error_NewContextGroupMustBeReadonly = () => mc(this.ERROR_NewContextGroupMustBeReadonly, `Group used in begin newContext must be readonly`); static ERROR_PostKeystrokeGroupMustBeReadonly = SevError | 0x070; - static Error_PostKeystrokeGroupMustBeReadonly = () => m(this.ERROR_PostKeystrokeGroupMustBeReadonly, `Group used in begin postKeystroke must be readonly`); + static Error_PostKeystrokeGroupMustBeReadonly = () => mc(this.ERROR_PostKeystrokeGroupMustBeReadonly, `Group used in begin postKeystroke must be readonly`); static ERROR_DuplicateGroup = SevError | 0x071; - static Error_DuplicateGroup = (o:KmcmpLibMessageParameters) => m( + static Error_DuplicateGroup = (o:KmcmpLibMessageParameters) => mc( this.ERROR_DuplicateGroup, `A group with the name '${o.p?.[0]}' has already been defined on line ${o.p?.[1]}.` ); static ERROR_DuplicateStore = SevError | 0x072; - static Error_DuplicateStore = (o:KmcmpLibMessageParameters) => m( + static Error_DuplicateStore = (o:KmcmpLibMessageParameters) => mc( this.ERROR_DuplicateStore, `A store with the name '${o.p?.[0]}' has already been defined on line ${o.p?.[1]}.` ); static ERROR_RepeatedBegin = SevError | 0x073; - static Error_RepeatedBegin = () => m(this.ERROR_RepeatedBegin, `Begin has already been set`); + static Error_RepeatedBegin = () => mc(this.ERROR_RepeatedBegin, `Begin has already been set`); static ERROR_VirtualKeyInContext = SevError | 0x074; - static Error_VirtualKeyInContext = () => m(this.ERROR_VirtualKeyInContext, `Virtual keys are not permitted in context`); + static Error_VirtualKeyInContext = () => mc(this.ERROR_VirtualKeyInContext, `Virtual keys are not permitted in context`); static ERROR_OutsTooLong = SevError | 0x075; - static Error_OutsTooLong = () => m(this.ERROR_OutsTooLong, `Store cannot be inserted with outs() as it makes the extended string too long`); + static Error_OutsTooLong = () => mc(this.ERROR_OutsTooLong, `Store cannot be inserted with outs() as it makes the extended string too long`); static ERROR_ExtendedStringTooLong = SevError | 0x076; - static Error_ExtendedStringTooLong = () => m(this.ERROR_ExtendedStringTooLong, `Extended string is too long`); + static Error_ExtendedStringTooLong = () => mc(this.ERROR_ExtendedStringTooLong, `Extended string is too long`); static ERROR_VirtualKeyExpansionTooLong = SevError | 0x077; - static Error_VirtualKeyExpansionTooLong = () => m(this.ERROR_VirtualKeyExpansionTooLong, `Virtual key expansion is too large`); + static Error_VirtualKeyExpansionTooLong = () => mc(this.ERROR_VirtualKeyExpansionTooLong, `Virtual key expansion is too large`); static ERROR_CharacterRangeTooLong = SevError | 0x078; - static Error_CharacterRangeTooLong = () => m(this.ERROR_CharacterRangeTooLong, `Character range is too large and cannot be expanded`); + static Error_CharacterRangeTooLong = () => mc(this.ERROR_CharacterRangeTooLong, `Character range is too large and cannot be expanded`); static ERROR_NonBMPCharactersNotSupportedInKeySection = SevError | 0x079; - static Error_NonBMPCharactersNotSupportedInKeySection = () => m(this.ERROR_NonBMPCharactersNotSupportedInKeySection, `Characters with codepoints over U+FFFF are not supported in the key part of the rule`); + static Error_NonBMPCharactersNotSupportedInKeySection = () => mc(this.ERROR_NonBMPCharactersNotSupportedInKeySection, `Characters with codepoints over U+FFFF are not supported in the key part of the rule`); static ERROR_InvalidTarget = SevError | 0x07A; - static Error_InvalidTarget = (o:KmcmpLibMessageParameters) => m( + static Error_InvalidTarget = (o:KmcmpLibMessageParameters) => mc( this.ERROR_InvalidTarget, `Unrecognized compile target '${o.p?.[0]}'` ); static ERROR_NoTargetsSpecified = SevError | 0x07B; - static Error_NoTargetsSpecified = () => m(this.ERROR_NoTargetsSpecified, `At least one compile target must be specified`); + static Error_NoTargetsSpecified = () => mc(this.ERROR_NoTargetsSpecified, `At least one compile target must be specified`); static WARN_TooManyWarnings = SevWarn | 0x080; - static Warn_TooManyWarnings = () => m(this.WARN_TooManyWarnings, `Too many warnings or errors`); + static Warn_TooManyWarnings = () => mc(this.WARN_TooManyWarnings, `Too many warnings or errors`); static WARN_OldVersion = SevWarn | 0x081; - static Warn_OldVersion = () => m(this.WARN_OldVersion, `The keyboard file is an old version`); + static Warn_OldVersion = () => mc(this.WARN_OldVersion, `The keyboard file is an old version`); static WARN_BitmapNotUsed = SevWarn | 0x082; - static Warn_BitmapNotUsed = () => m(this.WARN_BitmapNotUsed, `The 'bitmaps' statement is obsolete and only the first bitmap referred to will be used, you should use 'bitmap'.`); + static Warn_BitmapNotUsed = () => mc(this.WARN_BitmapNotUsed, `The 'bitmaps' statement is obsolete and only the first bitmap referred to will be used, you should use 'bitmap'.`); static WARN_CustomLanguagesNotSupported = SevWarn | 0x083; - static Warn_CustomLanguagesNotSupported = () => m(this.WARN_CustomLanguagesNotSupported, `Languages over 0x1FF, 0x1F are not supported correctly by Windows. You should use no LANGUAGE line instead.`); + static Warn_CustomLanguagesNotSupported = () => mc(this.WARN_CustomLanguagesNotSupported, `Languages over 0x1FF, 0x1F are not supported correctly by Windows. You should use no LANGUAGE line instead.`); static WARN_KeyBadLength = SevWarn | 0x084; - static Warn_KeyBadLength = () => m(this.WARN_KeyBadLength, `There are too many characters in the keystroke part of the rule.`); + static Warn_KeyBadLength = () => mc(this.WARN_KeyBadLength, `There are too many characters in the keystroke part of the rule.`); static WARN_IndexStoreShort = SevWarn | 0x085; - static Warn_IndexStoreShort = () => m(this.WARN_IndexStoreShort, `The store referenced in index() is shorter than the store referenced in any()`); + static Warn_IndexStoreShort = () => mc(this.WARN_IndexStoreShort, `The store referenced in index() is shorter than the store referenced in any()`); static WARN_UnicodeInANSIGroup = SevWarn | 0x086; - static Warn_UnicodeInANSIGroup = () => m(this.WARN_UnicodeInANSIGroup, `A Unicode character was found in an ANSI group`); + static Warn_UnicodeInANSIGroup = () => mc(this.WARN_UnicodeInANSIGroup, `A Unicode character was found in an ANSI group`); static WARN_ANSIInUnicodeGroup = SevWarn | 0x087; - static Warn_ANSIInUnicodeGroup = () => m(this.WARN_ANSIInUnicodeGroup, `An ANSI character was found in a Unicode group`); + static Warn_ANSIInUnicodeGroup = () => mc(this.WARN_ANSIInUnicodeGroup, `An ANSI character was found in a Unicode group`); static WARN_UnicodeSurrogateUsed = SevWarn | 0x088; - static Warn_UnicodeSurrogateUsed = () => m(this.WARN_UnicodeSurrogateUsed, `A Unicode surrogate character was found. You should use Unicode scalar values to represent values > U+FFFF`); + static Warn_UnicodeSurrogateUsed = () => mc(this.WARN_UnicodeSurrogateUsed, `A Unicode surrogate character was found. You should use Unicode scalar values to represent values > U+FFFF`); static WARN_ReservedCharacter = SevWarn | 0x089; - static Warn_ReservedCharacter = () => m(this.WARN_ReservedCharacter, `A Unicode character was found that should not be used`); + static Warn_ReservedCharacter = () => mc(this.WARN_ReservedCharacter, `A Unicode character was found that should not be used`); - static INFO_MinimumCoreEngineVersion = SevInfo | 0x08A; - static Info_MinimumCoreEngineVersion = (o:KmcmpLibMessageParameters) => m( + static INFO_MinimumCoreEngineVersion = SevInfo | 0x08A; + static Info_MinimumCoreEngineVersion = (o:KmcmpLibMessageParameters) => mc( this.INFO_MinimumCoreEngineVersion, - `The compiler has assigned a minimum engine version of ${o.p?.[0]}.${o.p?.[1]} based on features used in this keyboard` + `The compiler has assigned a minimum engine version of ${o.p?.[0]}.${o.p?.[1]} based on features used in this keyboard`, ); static WARN_VirtualKeyWithMnemonicLayout = SevWarn | 0x08B; - static Warn_VirtualKeyWithMnemonicLayout = () => m(this.WARN_VirtualKeyWithMnemonicLayout, `Virtual key used instead of virtual character key with a mnemonic layout`); + static Warn_VirtualKeyWithMnemonicLayout = () => mc(this.WARN_VirtualKeyWithMnemonicLayout, `Virtual key used instead of virtual character key with a mnemonic layout`); static WARN_VirtualCharKeyWithPositionalLayout = SevWarn | 0x08C; - static Warn_VirtualCharKeyWithPositionalLayout = () => m(this.WARN_VirtualCharKeyWithPositionalLayout, `Virtual character key used with a positional layout instead of mnemonic layout`); + static Warn_VirtualCharKeyWithPositionalLayout = () => mc(this.WARN_VirtualCharKeyWithPositionalLayout, `Virtual character key used with a positional layout instead of mnemonic layout`); static WARN_StoreAlreadyUsedAsOptionOrCall = SevWarn | 0x08D; - static Warn_StoreAlreadyUsedAsOptionOrCall = () => m(this.WARN_StoreAlreadyUsedAsOptionOrCall, `Store already used as an option or in a call statement and should not be used as a normal store`); + static Warn_StoreAlreadyUsedAsOptionOrCall = () => mc(this.WARN_StoreAlreadyUsedAsOptionOrCall, `Store already used as an option or in a call statement and should not be used as a normal store`); static WARN_StoreAlreadyUsedAsStoreOrCall = SevWarn | 0x08E; - static Warn_StoreAlreadyUsedAsStoreOrCall = () => m(this.WARN_StoreAlreadyUsedAsStoreOrCall, `Store already used as a normal store or in a call statement and should not be used as an option`); + static Warn_StoreAlreadyUsedAsStoreOrCall = () => mc(this.WARN_StoreAlreadyUsedAsStoreOrCall, `Store already used as a normal store or in a call statement and should not be used as an option`); static WARN_StoreAlreadyUsedAsStoreOrOption = SevWarn | 0x08F; - static Warn_StoreAlreadyUsedAsStoreOrOption = () => m(this.WARN_StoreAlreadyUsedAsStoreOrOption, `Store already used as a normal store or as an option and should not be used in a call statement`); + static Warn_StoreAlreadyUsedAsStoreOrOption = () => mc(this.WARN_StoreAlreadyUsedAsStoreOrOption, `Store already used as a normal store or as an option and should not be used in a call statement`); static WARN_PunctuationInEthnologueCode = SevWarn | 0x090; - static Warn_PunctuationInEthnologueCode = () => m(this.WARN_PunctuationInEthnologueCode, `Punctuation should not be used to separate Ethnologue codes; instead use spaces`); + static Warn_PunctuationInEthnologueCode = () => mc(this.WARN_PunctuationInEthnologueCode, `Punctuation should not be used to separate Ethnologue codes; instead use spaces`); static WARN_TouchLayoutMissingLayer = SevWarn | 0x091; - static Warn_TouchLayoutMissingLayer = (o:{keyId:string, platformName:string, layerId:string, nextLayer:string, address:KeyAddress}) => mw(this.WARN_TouchLayoutMissingLayer, - `Key "${def(o.keyId)}" on platform "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}), references a missing layer "${def(o.nextLayer)}"`); + static Warn_TouchLayoutMissingLayer = (o:{keyId:string, platformName:string, layerId:string, nextLayer:string, address:KeyAddress}) => mw( + this.WARN_TouchLayoutMissingLayer, + `Key "${def(o.keyId)}" on platform "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}), references a missing layer "${def(o.nextLayer)}"`, + ); static WARN_TouchLayoutCustomKeyNotDefined = SevWarn | 0x092; - static Warn_TouchLayoutCustomKeyNotDefined = (o:{keyId:string, platformName:string, layerId:string, address:KeyAddress}) => mw(this.WARN_TouchLayoutCustomKeyNotDefined, - `Key "${def(o.keyId)}" on platform "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}), is a custom key but has no corresponding rule in the source.`); + static Warn_TouchLayoutCustomKeyNotDefined = (o:{keyId:string, platformName:string, layerId:string, address:KeyAddress}) => mw( + this.WARN_TouchLayoutCustomKeyNotDefined, + `Key "${def(o.keyId)}" on platform "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}), is a custom key but has no corresponding rule in the source.`, + ); static WARN_TouchLayoutMissingRequiredKeys = SevWarn | 0x093; - static Warn_TouchLayoutMissingRequiredKeys = (o:{layerId:string, platformName:string, missingKeys:string}) => mw(this.WARN_TouchLayoutMissingRequiredKeys, - `Layer "${def(o.layerId)}" on platform "${def(o.platformName)}" is missing the required key(s) '${def(o.missingKeys)}'.`); + static Warn_TouchLayoutMissingRequiredKeys = (o:{layerId:string, platformName:string, missingKeys:string}) => mw( + this.WARN_TouchLayoutMissingRequiredKeys, + `Layer "${def(o.layerId)}" on platform "${def(o.platformName)}" is missing the required key(s) '${def(o.missingKeys)}'.`, + ); static WARN_HelpFileMissing = SevWarn | 0x094; - static Warn_HelpFileMissing = (o:{line:number, helpFilename:string, e:any}) => mw(this.WARN_HelpFileMissing, - `File ${def(o.helpFilename)} could not be loaded: ${(o.e??'').toString()}`,o); + static Warn_HelpFileMissing = (o:{line:number, helpFilename:string, e:any}) => mw( + this.WARN_HelpFileMissing, + `File ${def(o.helpFilename)} could not be loaded: ${(o.e??'').toString()}`, o, + ); static WARN_EmbedJsFileMissing = SevWarn | 0x095; - static Warn_EmbedJsFileMissing = (o:{line:number, jsFilename: string, e:any}) => mw(this.WARN_EmbedJsFileMissing, - `File ${def(o.jsFilename)} could not be loaded: ${(o.e??'').toString()}`, o); + static Warn_EmbedJsFileMissing = (o:{line:number, jsFilename: string, e:any}) => mw( + this.WARN_EmbedJsFileMissing, + `File ${def(o.jsFilename)} could not be loaded: ${(o.e??'').toString()}`, o, + ); // static WARN_TouchLayoutFileMissing = SevWarn | 0x096; // static WARN_VisualKeyboardFileMissing = SevWarn | 0x097; static WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb = SevWarn | 0x098; - static Warn_ExtendedShiftFlagsNotSupportedInKeymanWeb = (o:{line:number,flags:string}) => mw(this.WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, - `Extended shift flags ${def(o.flags)} are not supported in KeymanWeb`, o); + static Warn_ExtendedShiftFlagsNotSupportedInKeymanWeb = (o:{line:number,flags:string}) => mw( + this.WARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, + `Extended shift flags ${def(o.flags)} are not supported in KeymanWeb`, o, + ); static WARN_TouchLayoutUnidentifiedKey = SevWarn | 0x099; - static Warn_TouchLayoutUnidentifiedKey = (o:{layerId:string, address:KeyAddress}) => mw(this.WARN_TouchLayoutUnidentifiedKey, - `A key (${keyAddress(o.address)}) on layer "${def(o.layerId)}" has no identifier.`); + static Warn_TouchLayoutUnidentifiedKey = (o:{layerId:string, address:KeyAddress}) => mw( + this.WARN_TouchLayoutUnidentifiedKey, + `A key (${keyAddress(o.address)}) on layer "${def(o.layerId)}" has no identifier.`, + ); static HINT_UnreachableKeyCode = SevHint | 0x09A; - static Hint_UnreachableKeyCode = (o:{line:number,key:string}) => mw(this.HINT_UnreachableKeyCode, - `The rule will never be matched for key ${def(o.key)} because its key code is never fired.`, o); + static Hint_UnreachableKeyCode = (o:{line:number,key:string}) => mw( + this.HINT_UnreachableKeyCode, + `The rule will never be matched for key ${def(o.key)} because its key code is never fired.`, o, + ); // static WARN_CouldNotCopyJsonFile = SevWarn | 0x09B; static WARN_PlatformNotInTargets = SevWarn | 0x09C; - static Warn_PlatformNotInTargets = () => m(this.WARN_PlatformNotInTargets, `The specified platform is not a target platform`); + static Warn_PlatformNotInTargets = () => mc(this.WARN_PlatformNotInTargets, `The specified platform is not a target platform`); static WARN_HeaderStatementIsDeprecated = SevWarn | 0x09D; - static Warn_HeaderStatementIsDeprecated = () => m(this.WARN_HeaderStatementIsDeprecated, `Header statements are deprecated; use instead the equivalent system store`); + static Warn_HeaderStatementIsDeprecated = () => mc(this.WARN_HeaderStatementIsDeprecated, `Header statements are deprecated; use instead the equivalent system store`); static WARN_UseNotLastStatementInRule = SevWarn | 0x09E; - static Warn_UseNotLastStatementInRule = () => m(this.WARN_UseNotLastStatementInRule, `A rule with use() statements in the output should not have other content following the use() statements`); + static Warn_UseNotLastStatementInRule = () => mc(this.WARN_UseNotLastStatementInRule, `A rule with use() statements in the output should not have other content following the use() statements`); static WARN_TouchLayoutFontShouldBeSameForAllPlatforms = SevWarn | 0x09F; - static Warn_TouchLayoutFontShouldBeSameForAllPlatforms = () => mw(this.WARN_TouchLayoutFontShouldBeSameForAllPlatforms, - `The touch layout font should be the same for all platforms.`); + static Warn_TouchLayoutFontShouldBeSameForAllPlatforms = () => mw( + this.WARN_TouchLayoutFontShouldBeSameForAllPlatforms, + `The touch layout font should be the same for all platforms.`, + ); // static WARN_InvalidJSONMetadataFile = SevWarn | 0x0A0; // static WARN_JSONMetadataOSKFontShouldMatchTouchFont = SevWarn | 0x0A1; static WARN_KVKFileIsInSourceFormat = SevWarn | 0x0A2; - static Warn_KVKFileIsInSourceFormat = () => m(this.WARN_KVKFileIsInSourceFormat, `.kvk file should be binary but is an XML file`); + static Warn_KVKFileIsInSourceFormat = () => mc(this.WARN_KVKFileIsInSourceFormat, `.kvk file should be binary but is an XML file`); // kmcmplib: static Warn_DontMixChiralAndNonChiralModifiers = () => m(this.WARN_DontMixChiralAndNonChiralModifiers, `Don't mix the use of left/right modifiers with non-left/right modifiers in the same platform`); static WARN_DontMixChiralAndNonChiralModifiers = SevWarn | 0x0A3; - static Warn_DontMixChiralAndNonChiralModifiers = () => mw(this.WARN_DontMixChiralAndNonChiralModifiers, - `This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.`); + static Warn_DontMixChiralAndNonChiralModifiers = () => mw( + this.WARN_DontMixChiralAndNonChiralModifiers, + `This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.`, + ); static WARN_MixingLeftAndRightModifiers = SevWarn | 0x0A4; - static Warn_MixingLeftAndRightModifiers = () => m(this.WARN_MixingLeftAndRightModifiers, `Left and right modifiers should not both be used in the same rule`); + static Warn_MixingLeftAndRightModifiers = () => mc(this.WARN_MixingLeftAndRightModifiers, `Left and right modifiers should not both be used in the same rule`); static WARN_LanguageHeadersDeprecatedInKeyman10 = SevWarn | 0x0A5; - static Warn_LanguageHeadersDeprecatedInKeyman10 = () => m(this.WARN_LanguageHeadersDeprecatedInKeyman10, `This language header has been deprecated in Keyman 10. Instead, add language metadata in the package file`); + static Warn_LanguageHeadersDeprecatedInKeyman10 = () => mc(this.WARN_LanguageHeadersDeprecatedInKeyman10, `This language header has been deprecated in Keyman 10. Instead, add language metadata in the package file`); static HINT_NonUnicodeFile = SevHint | 0x0A6; - static Hint_NonUnicodeFile = () => m(this.HINT_NonUnicodeFile, `Keyman Developer has detected that the file has ANSI encoding. Consider converting this file to UTF-8`); + static Hint_NonUnicodeFile = () => mc(this.HINT_NonUnicodeFile, `Keyman Developer has detected that the file has ANSI encoding. Consider converting this file to UTF-8`); // static WARN_TooManyErrorsOrWarnings = SevWarn | 0x0A7; static WARN_HotkeyHasInvalidModifier = SevWarn | 0x0A8; - static Warn_HotkeyHasInvalidModifier = () => m(this.WARN_HotkeyHasInvalidModifier, `Hotkey has modifiers that are not supported. Use only SHIFT, CTRL and ALT`); + static Warn_HotkeyHasInvalidModifier = () => mc(this.WARN_HotkeyHasInvalidModifier, `Hotkey has modifiers that are not supported. Use only SHIFT, CTRL and ALT`); static WARN_TouchLayoutSpecialLabelOnNormalKey = SevWarn | 0x0A9; - static Warn_TouchLayoutSpecialLabelOnNormalKey = (o:{keyId:string, platformName:string, layerId:string, label:string, address:KeyAddress}) => - mw(this.WARN_TouchLayoutSpecialLabelOnNormalKey, + static Warn_TouchLayoutSpecialLabelOnNormalKey = (o:{keyId:string, platformName:string, layerId:string, label:string, address:KeyAddress}) => mw( + this.WARN_TouchLayoutSpecialLabelOnNormalKey, `Key "${def(o.keyId)}" on platform "${def(o.platformName)}", layer "${def(o.layerId)}" (${keyAddress(o.address)}) does not have `+ - `the key type "Special" or "Special (active)" but has the label "${def(o.label)}". This feature is only supported in Keyman 14 or later`); + `the key type "Special" or "Special (active)" but has the label "${def(o.label)}". This feature is only supported in Keyman 14 or later`, + ); static WARN_OptionStoreNameInvalid = SevWarn | 0x0AA; - static Warn_OptionStoreNameInvalid = (o:{name:string}) => mw(this.WARN_OptionStoreNameInvalid, - `The option store ${def(o.name)} should be named with characters in the range A-Z, a-z, 0-9 and _ only.`); + static Warn_OptionStoreNameInvalid = (o:{name:string}) => mw( + this.WARN_OptionStoreNameInvalid, + `The option store ${def(o.name)} should be named with characters in the range A-Z, a-z, 0-9 and _ only.`, + ); static WARN_NulNotFirstStatementInContext = SevWarn | 0x0AB; - static Warn_NulNotFirstStatementInContext = () => m(this.WARN_NulNotFirstStatementInContext, `nul must be the first statement in the context`); + static Warn_NulNotFirstStatementInContext = () => mc(this.WARN_NulNotFirstStatementInContext, `nul must be the first statement in the context`); static WARN_IfShouldBeAtStartOfContext = SevWarn | 0x0AC; - static Warn_IfShouldBeAtStartOfContext = () => m(this.WARN_IfShouldBeAtStartOfContext, `if, platform and baselayout should be at start of context (after nul, if present)`); + static Warn_IfShouldBeAtStartOfContext = () => mc(this.WARN_IfShouldBeAtStartOfContext, `if, platform and baselayout should be at start of context (after nul, if present)`); static WARN_KeyShouldIncludeNCaps = SevWarn | 0x0AD; - static Warn_KeyShouldIncludeNCaps = () => m(this.WARN_KeyShouldIncludeNCaps, `Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches`); + static Warn_KeyShouldIncludeNCaps = () => mc(this.WARN_KeyShouldIncludeNCaps, `Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches`); static HINT_UnreachableRule = SevHint | 0x0AE; - static Hint_UnreachableRule = (o:KmcmpLibMessageParameters) => m( + static Hint_UnreachableRule = (o:KmcmpLibMessageParameters) => mc( this.HINT_UnreachableRule, `This rule will never be matched as the rule on line ${o.p?.[0]} takes precedence` ); static WARN_VirtualKeyInOutput = SevWarn | 0x0AF; - static Warn_VirtualKeyInOutput = () => m(this.WARN_VirtualKeyInOutput, `Virtual keys are not supported in output`); + static Warn_VirtualKeyInOutput = () => mc(this.WARN_VirtualKeyInOutput, `Virtual keys are not supported in output`); static HINT_IndexStoreLong = SevHint | 0x0B0; - static Hint_IndexStoreLong = () => m( + static Hint_IndexStoreLong = () => mc( this.HINT_IndexStoreLong, `The store referenced in index() is longer than the store referenced in any()`, ); static ERROR_ContextExCannotReferenceIf = SevError | 0x0B1; - static Error_ContextExCannotReferenceIf = () => m( + static Error_ContextExCannotReferenceIf = () => mc( this.ERROR_ContextExCannotReferenceIf, `The offset in context() points to a non-character if() statement in the context`, ); static ERROR_ContextExCannotReferenceNul = SevError | 0x0B2; - static Error_ContextExCannotReferenceNul = () => m( + static Error_ContextExCannotReferenceNul = () => mc( this.ERROR_ContextExCannotReferenceNul, `The offset in context() points to a non-character nul statement in the context`, ); static ERROR_TextBeforeOrAfterNulInOutput = SevError | 0x0B3; - static Error_TextBeforeOrAfterNulInOutput = () => m( + static Error_TextBeforeOrAfterNulInOutput = () => mc( this.ERROR_TextBeforeOrAfterNulInOutput, `A rule with a nul statement in the output cannot also output text or text-emitting statements`, `If a rule has [\`nul\`](https://help.keyman.com/developer/language/reference/nul) @@ -774,66 +863,70 @@ export class KmnCompilerMessages { ); static ERROR_NameMustBeAtLeastOneCharLong = SevError | 0x0B4; - static Error_NameMustBeAtLeastOneCharLong = () => m( + static Error_NameMustBeAtLeastOneCharLong = () => mc( this.ERROR_NameMustBeAtLeastOneCharLong, `The name parameter is required`, ); static ERROR_NameMustBeAtMostNCharsLong = SevError | 0x0B5; - static Error_NameMustBeAtMostNCharsLong = (o:{name:string,length:string}) => m( + static Error_NameMustBeAtMostNCharsLong = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameMustBeAtMostNCharsLong, - `The referenced name '${def(o.name)}' must be at most ${def(o.length)} characters long`, + `The referenced name '${def(o.p?.[0])}' must be at most ${def(o.p?.[1])} characters long`, ); static ERROR_NameContainsInvalidCharacter = SevError | 0x0B6; - static Error_NameContainsInvalidCharacter = (o:{name:string}) => m( + static Error_NameContainsInvalidCharacter = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameContainsInvalidCharacter, - `The referenced name '${def(o.name)}' contains an invalid character`, + `The referenced name '${def(o.p?.[0])}' contains an invalid character`, `Names (or identifiers) must not contain spaces, commas, parentheses, square brackets, control characters, or Unicode non-characters.` ); static ERROR_NameMustNotContainSpaces = SevError | 0x0B7; - static Error_NameMustNotContainSpaces = (o:{name:string}) => m( + static Error_NameMustNotContainSpaces = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameMustNotContainSpaces, - `The referenced name '${def(o.name)}' must not contain spaces`, + `The referenced name '${def(o.p?.[0])}' must not contain spaces`, `Names (or identifiers) must not contain spaces, commas, parentheses, square brackets, control characters, or Unicode non-characters.` ); static ERROR_NameMustNotContainComma = SevError | 0x0B8; - static Error_NameMustNotContainComma = (o:{name:string}) => m( + static Error_NameMustNotContainComma = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameMustNotContainComma, - `The referenced name '${def(o.name)}' must not contain commas`, + `The referenced name '${def(o.p?.[0])}' must not contain commas`, `Names (or identifiers) must not contain spaces, commas, parentheses, square brackets, control characters, or Unicode non-characters.` ); static ERROR_NameMustNotContainParentheses = SevError | 0x0B9; - static Error_NameMustNotContainParentheses = (o:{name:string}) => m( + static Error_NameMustNotContainParentheses = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameMustNotContainParentheses, - `The referenced name '${def(o.name)}' must not contain opening or closing parentheses`, + `The referenced name '${def(o.p?.[0])}' must not contain opening or closing parentheses`, `Names (or identifiers) must not contain spaces, commas, parentheses, square brackets, control characters, or Unicode non-characters.` ); static ERROR_NameMustNotContainSquareBrackets = SevError | 0x0BA; - static Error_NameMustNotContainSquareBrackets = (o:{name:string}) => m( + static Error_NameMustNotContainSquareBrackets = (o: KmcmpLibMessageParameters) => mc( this.ERROR_NameMustNotContainSquareBrackets, - `The referenced name '${def(o.name)}' must not contain opening or closing square brackets`, + `The referenced name '${def(o.p?.[0])}' must not contain opening or closing square brackets`, `Names (or identifiers) must not contain spaces, commas, parentheses, square brackets, control characters, or Unicode non-characters.` ); static WARN_DeprecatedStatement = SevWarn | 0x0BB; - static Warn_DeprecatedStatement = (o: KmcmpLibMessageParameters) => m( + static Warn_DeprecatedStatement = (o: KmcmpLibMessageParameters) => mc( this.WARN_DeprecatedStatement, `The statement '${def(o.p?.[0])}' has been deprecated in Keyman ${def(o.p?.[1])}`, ); static FATAL_BufferOverflow = SevFatal | 0x0C0; - static Fatal_BufferOverflow = () => m(this.FATAL_BufferOverflow, `The compiler memory buffer overflowed`); + static Fatal_BufferOverflow = () => mc(this.FATAL_BufferOverflow, `The compiler memory buffer overflowed`); // static FATAL_Break = SevFatal | 0x0C1; - // static Fatal_Break = () => m(this.FATAL_Break, `Compiler interrupted by user`); + // static Fatal_Break = () => mc(this.FATAL_Break, `Compiler interrupted by user`); + + // ------------------------------------------------------------------------------------------------ + // end of kmcmplib messages + // ------------------------------------------------------------------------------------------------ }; diff --git a/developer/src/kmc-kmn/test/kmn-compiler-messages.tests.ts b/developer/src/kmc-kmn/test/kmn-compiler-messages.tests.ts index 09466f7229..d34c791f48 100644 --- a/developer/src/kmc-kmn/test/kmn-compiler-messages.tests.ts +++ b/developer/src/kmc-kmn/test/kmn-compiler-messages.tests.ts @@ -3,9 +3,24 @@ import { assert } from 'chai'; import { CompilerErrorMask, CompilerErrorNamespace } from '@keymanapp/developer-utils'; import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers'; import { KmnCompiler } from '../src/main.js'; -import { KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js'; +import { KmcKmnCompilerEvent, KmnCompilerMessageRanges, KmnCompilerMessages } from '../src/compiler/kmn-compiler-messages.js'; import { makePathToFixture } from './helpers/index.js'; + +// Source - https://stackoverflow.com/a/9924463 +// Posted by Jack Allan, modified by community. See post 'Timeline' for change history +// Retrieved 2026-09-01, License - CC BY-SA 3.0 +function getParamNames(func: any) { + const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/mg; + const ARGUMENT_NAMES = /([^\s,]+)/g; + const fnStr = func.toString().replace(STRIP_COMMENTS, ''); + let result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); + if(result === null) + result = []; + return result; +} + + describe('KmnCompilerMessages', function () { const callbacks = new TestCompilerCallbacks(this); @@ -13,6 +28,53 @@ describe('KmnCompilerMessages', function () { return verifyCompilerMessagesObject(KmnCompilerMessages, CompilerErrorNamespace.KmnCompiler); }); + it('should have correct parameter types and numeric ranges for kmcmplib vs kmw vs kmc-kmn messages', function() { + // See comment in kmn-compiler-messages.ts for logic. + // This function follows the same pattern as `verifyCompilerMessagesObject` but with specific tests for + // this more constrained object + const toTitleCase = (s: string) => s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase(); + const keys = Object.keys(KmnCompilerMessages); + const m = KmnCompilerMessages as Record; + + for(const key of keys) { + if(typeof m[key] == 'number') { + const o = /^(DEBUG|VERBOSE|INFO|HINT|WARN|ERROR|FATAL)_([A-Za-z0-9_]+)$/.exec(key); + const f = toTitleCase(o[1]) + '_' + o[2]; + // note: validation done in verifyCompilerMessagesObject, don't repeat it here + + const v: KmcKmnCompilerEvent = m[f]('','','','','','','','','','','','' /* ignore arguments*/); + + const code = m[key] & CompilerErrorMask.BaseError; + const hex = code.toString(16).padStart(3, '0'); + + if(code >= KmnCompilerMessageRanges.RANGE_CompilerMessage_Min &&code <= KmnCompilerMessageRanges.RANGE_CompilerMessage_Max) { + // kmc-kmn messages, should not be using mw() function or mc() function + // + assert.equal(v.kmcKmnSource, 'kmc-kmn', `expected ${v.kmcKmnSource} to equal 'kmc-kmn' for ${hex}, '${key}'.`); + } else if(code >= KmnCompilerMessageRanges.RANGE_KMN_COMPILER_MIN && code <= KmnCompilerMessageRanges.RANGE_KMN_COMPILER_MAX) { + // kmcmplib or kmw compiler messages, should not be using m() function or mx() function + assert.oneOf(v.kmcKmnSource, ['kmcmplib', 'kmw-compiler'], `expected ${v.kmcKmnSource} to equal 'kmcmplib' or 'kmw-compiler for ${hex}, '${key}'.`); + if(v.kmcKmnSource == 'kmcmplib') { + // The only allowed param is an object o with property p. We + // cannot test parameter shape directly, so we will compare + // outputs of calling if o.p is set, which should not match what + // we get when o.p is not set. + const params = getParamNames(m[f]); + if(params.length) { + const v2: KmcKmnCompilerEvent = m[f]({p:['1','2','3','4','5','6','7','8','9']}); + assert.notEqual(v.message, v2.message, `Message '${key}' (${hex}) must use KmcmpLibMessageParameters pattern`); + } + } + } else if(code >= KmnCompilerMessageRanges.RANGE_LEXICAL_MODEL_MIN && code <= KmnCompilerMessageRanges.RANGE_LEXICAL_MODEL_MAX) { + assert.fail(`Message identifier ${hex} for '${key}' is reserved and should not be used (LEXICAL_MODEL range)`); + } else { + assert.fail(`Message identifier ${hex} for '${key}' is out of range`); + } + } + } + + }); + it('should have a 1:1 correspondence with kmn_compiler_errors.h', function() { const headerFilename = 'kmn_compiler_errors.h';