diff --git a/developer/src/common/delphi/compiler/CompileErrorCodes.pas b/developer/src/common/delphi/compiler/CompileErrorCodes.pas index 557c5276a06..81c0c5334fb 100644 --- a/developer/src/common/delphi/compiler/CompileErrorCodes.pas +++ b/developer/src/common/delphi/compiler/CompileErrorCodes.pas @@ -166,6 +166,7 @@ interface CERR_DuplicateGroup = $4071; CERR_DuplicateStore = $4072; CERR_RepeatedBegin = $4073; + CERR_VirtualKeyInContext = $4074; CWARN_TooManyWarnings = $2080; CWARN_OldVersion = $2081; diff --git a/developer/src/common/include/kmn_compiler_errors.h b/developer/src/common/include/kmn_compiler_errors.h index 9944c61304e..fe7ba11a150 100644 --- a/developer/src/common/include/kmn_compiler_errors.h +++ b/developer/src/common/include/kmn_compiler_errors.h @@ -171,8 +171,8 @@ #define CERR_DuplicateGroup 0x00004071 #define CERR_DuplicateStore 0x00004072 - #define CERR_RepeatedBegin 0x00004073 +#define CERR_VirtualKeyInContext 0x00004074 #define CWARN_TooManyWarnings 0x00002080 #define CWARN_OldVersion 0x00002081 diff --git a/developer/src/kmc-kmn/src/compiler/messages.ts b/developer/src/kmc-kmn/src/compiler/messages.ts index 8124d398c15..cbd35f85155 100644 --- a/developer/src/kmc-kmn/src/compiler/messages.ts +++ b/developer/src/kmc-kmn/src/compiler/messages.ts @@ -233,8 +233,8 @@ export class KmnCompilerMessages { static ERROR_DuplicateGroup = SevError | 0x071; static ERROR_DuplicateStore = SevError | 0x072; - static ERROR_RepeatedBegin = SevError | 0x073; + static ERROR_VirtualKeyInContext = SevError | 0x074; static WARN_TooManyWarnings = SevWarn | 0x080; static WARN_OldVersion = SevWarn | 0x081; diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_group.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_duplicate_group.kmn similarity index 100% rename from developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_group.kmn rename to developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_duplicate_group.kmn diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_store.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_duplicate_store.kmn similarity index 100% rename from developer/src/kmc-kmn/test/fixtures/invalid-keyboards/cerr_duplicate_store.kmn rename to developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_duplicate_store.kmn diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_virtual_key_in_context.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_virtual_key_in_context.kmn new file mode 100644 index 00000000000..3309795d8e4 --- /dev/null +++ b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/error_virtual_key_in_context.kmn @@ -0,0 +1,9 @@ +store(&NAME) 'ERROR_VirtualKeyInContext' +store(&VERSION) '9.0' + +begin Unicode > use(main) + +group(main) using keys + +c ERROR_VirtualKeyInContext +[K_BKQUOTE] + 'a' > 'b' diff --git a/developer/src/kmc-kmn/test/test-messages.ts b/developer/src/kmc-kmn/test/test-messages.ts index 72624f9599c..9d91fdcd55e 100644 --- a/developer/src/kmc-kmn/test/test-messages.ts +++ b/developer/src/kmc-kmn/test/test-messages.ts @@ -1,6 +1,6 @@ import 'mocha'; import { assert } from 'chai'; -import { CompilerMessages } from '../src/compiler/messages.js'; +import { CompilerMessages, KmnCompilerMessages } from '../src/compiler/messages.js'; import { TestCompilerCallbacks, verifyCompilerMessagesObject } from '@keymanapp/developer-test-helpers'; import { makePathToFixture } from './helpers/index.js'; import { KmnCompiler } from '../src/main.js'; @@ -54,15 +54,22 @@ describe('CompilerMessages', function () { // CERR_DuplicateGroup it('should generate CERR_DuplicateGroup if the kmn contains two groups with the same name', async function() { - await testForMessage(this, ['invalid-keyboards', 'cerr_duplicate_group.kmn'], 0x302071); //TODO: consolidate messages from kmcmplib, CompilerMessages.CERR_DuplicateGroup + await testForMessage(this, ['invalid-keyboards', 'error_duplicate_group.kmn'], KmnCompilerMessages.ERROR_DuplicateGroup); assert.equal(callbacks.messages[0].message, "A group with this name has already been defined. Group 'ខ្មែរ' declared on line 9"); }); // CERR_DuplicateStore it('should generate CERR_DuplicateStore if the kmn contains two stores with the same name', async function() { - await testForMessage(this, ['invalid-keyboards', 'cerr_duplicate_store.kmn'], 0x302072); //TODO: consolidate messages from kmcmplib, CompilerMessages.CERR_DuplicateStore + await testForMessage(this, ['invalid-keyboards', 'error_duplicate_store.kmn'], KmnCompilerMessages.ERROR_DuplicateStore); assert.equal(callbacks.messages[0].message, "A store with this name has already been defined. Store 'ខ្មែរ' declared on line 11"); }); + // CERR_VirtualKeyInContext + + it('should generate ERROR_VirtualKeyInContext if a virtual key is found in the context part of a rule', async function() { + await testForMessage(this, ['invalid-keyboards', 'error_virtual_key_in_context.kmn'], KmnCompilerMessages.ERROR_VirtualKeyInContext); + assert.equal(callbacks.messages[0].message, "Virtual keys are not permitted in context"); + }); + }); diff --git a/developer/src/kmcmplib/src/CompMsg.cpp b/developer/src/kmcmplib/src/CompMsg.cpp index 3e2e894d3cf..8ab5db81f6b 100644 --- a/developer/src/kmcmplib/src/CompMsg.cpp +++ b/developer/src/kmcmplib/src/CompMsg.cpp @@ -110,6 +110,7 @@ const struct CompilerError CompilerErrors[] = { { CERR_DuplicateGroup , "A group with this name has already been defined."}, { CERR_DuplicateStore , "A store with this name has already been defined."}, { CERR_RepeatedBegin , "Begin has already been set"}, + { CERR_VirtualKeyInContext , "Virtual keys are not permitted in context"}, { CHINT_UnreachableRule , "This rule will never be matched as another rule takes precedence"}, { CHINT_NonUnicodeFile , "Keyman Developer has detected that the file has ANSI encoding. Consider converting this file to UTF-8"}, diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 3634d5d5d8b..e2720f8608e 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1295,10 +1295,11 @@ KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR co } /** - *Checks that the order of statements in the context matches the specification + * Checks that the order of statements in the context matches the specification. * Rule structure: [context] ['+' key] '>' output * Context structure: [nul] [if()|baselayout()|platform()]+ [char|any|context()|deadkey()|dk()|index()|notany()|outs()] - * Test that nul is first, then if(), baselayout(), platform() statements are before any other content + * Test that nul is first, then if(), baselayout(), platform() statements are before any other content. + * Also verifies that virtual keys are not found in the context. */ KMX_BOOL CheckContextStatementPositions(PKMX_WCHAR context) { KMX_BOOL hadContextChar = FALSE; @@ -1316,6 +1317,9 @@ KMX_BOOL CheckContextStatementPositions(PKMX_WCHAR context) { AddWarningBool(CWARN_IfShouldBeAtStartOfContext); } break; + case CODE_EXTENDED: + AddCompileError(CERR_VirtualKeyInContext); + break; default: hadContextChar = TRUE; }