mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-22 07:37:40 +00:00
feat(developer): refactor a little bit to give a postValidate() phase
- postValidate() is called after all other compilation happens - also make SectionCompiler actually abstract - test fixes to support this For: #9446
This commit is contained in:
parent
feb2296dbc
commit
eebb88699d
4 changed files with 47 additions and 17 deletions
|
|
@ -207,6 +207,13 @@ export class LdmlKeyboardCompiler {
|
|||
kmx.kmxplus[section.id] = sect as any;
|
||||
}
|
||||
|
||||
// give all sections a chance to postValidate
|
||||
for(let section of sections) {
|
||||
if(!section.postValidate(kmx.kmxplus[section.id])) {
|
||||
passed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return passed ? kmx : null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { LDMLKeyboard, KMXPlus, CompilerCallbacks } from "@keymanapp/common-types";
|
||||
import { SectionIdent, constants } from '@keymanapp/ldml-keyboard-constants';
|
||||
|
||||
/* istanbul ignore next */
|
||||
export class SectionCompiler {
|
||||
/** newable interface to SectionCompiler c'tor */
|
||||
export type SectionCompilerNew = new (source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, callbacks: CompilerCallbacks) => SectionCompiler;
|
||||
export abstract class SectionCompiler {
|
||||
protected readonly keyboard3: LDMLKeyboard.LKKeyboard;
|
||||
protected readonly callbacks: CompilerCallbacks;
|
||||
|
||||
|
|
@ -11,19 +12,34 @@ export class SectionCompiler {
|
|||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
/* c8 ignore next 11 */
|
||||
public get id(): SectionIdent {
|
||||
throw Error(`Internal Error: id() not implemented`);
|
||||
}
|
||||
|
||||
public compile(sections: KMXPlus.DependencySections): KMXPlus.Section {
|
||||
throw Error(`Internal Error: compile() not implemented`);
|
||||
}
|
||||
public abstract get id(): SectionIdent;
|
||||
|
||||
/**
|
||||
* This is called before compile.
|
||||
* @returns false if this compiler failed to validate.
|
||||
*/
|
||||
public validate(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the compilation for this section, returning the correct Section subclass
|
||||
* object.
|
||||
*
|
||||
* @param sections any declared dependency sections per dependencies()
|
||||
*/
|
||||
public abstract compile(sections: KMXPlus.DependencySections): KMXPlus.Section;
|
||||
|
||||
/**
|
||||
* This is called after all other compile phases have completed, and provides an
|
||||
* opportunity for late error reporting, for example for invalid strings.
|
||||
* @param section the compiled section, if any.
|
||||
* @returns false if validate fails
|
||||
*/
|
||||
public postValidate(section?: KMXPlus.Section): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dependencies for this compiler.
|
||||
* @returns set of dependent sections
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { MarkerTracker, MarkerUse } from "./marker-tracker.js";
|
|||
|
||||
type TransformCompilerType = 'simple' | 'backspace';
|
||||
|
||||
export class TransformCompiler<T extends TransformCompilerType, TranBase extends Tran> extends SectionCompiler {
|
||||
export abstract class TransformCompiler<T extends TransformCompilerType, TranBase extends Tran> extends SectionCompiler {
|
||||
|
||||
static validateMarkers(keyboard: LDMLKeyboard.LKKeyboard, mt : MarkerTracker): boolean {
|
||||
keyboard?.transforms?.forEach(transforms =>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import 'mocha';
|
||||
import * as path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { SectionCompiler } from '../../src/compiler/section-compiler.js';
|
||||
import { SectionCompiler, SectionCompilerNew } from '../../src/compiler/section-compiler.js';
|
||||
import { KMXPlus, LDMLKeyboardXMLSourceFileReader, VisualKeyboard, CompilerEvent, LDMLKeyboardTestDataXMLSourceFile, compilerEventFormat, LDMLKeyboard, UnicodeSetParser, CompilerCallbacks } from '@keymanapp/common-types';
|
||||
import { LdmlKeyboardCompiler } from '../../src/main.js'; // make sure main.js compiles
|
||||
import { assert } from 'chai';
|
||||
|
|
@ -52,7 +52,7 @@ afterEach(function() {
|
|||
});
|
||||
|
||||
|
||||
export async function loadSectionFixture(compilerClass: typeof SectionCompiler, filename: string, callbacks: TestCompilerCallbacks, dependencies?: typeof SectionCompiler[]): Promise<Section> {
|
||||
export async function loadSectionFixture(compilerClass: SectionCompilerNew, filename: string, callbacks: TestCompilerCallbacks, dependencies?: SectionCompilerNew[], postValidateFail?: boolean): Promise<Section> {
|
||||
callbacks.messages = [];
|
||||
const inputFilename = makePathToFixture(filename);
|
||||
const data = callbacks.loadFile(inputFilename);
|
||||
|
|
@ -83,13 +83,16 @@ export async function loadSectionFixture(compilerClass: typeof SectionCompiler,
|
|||
compiler.dependencies.forEach(dep => assert.ok(sections[dep],
|
||||
`Required dependency '${dep}' for '${compiler.id}' was not supplied: Check the 'dependencies' argument to loadSectionFixture or testCompilationCases`));
|
||||
|
||||
return compiler.compile(sections);
|
||||
const section = await compiler.compile(sections);
|
||||
const postValidate = compiler.postValidate(section);
|
||||
assert.equal(postValidate, !postValidateFail, `expected postValidate() to return ${!postValidateFail}`);
|
||||
return section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively load dependencies. Normally they are loaded in SECTION_COMPILERS order
|
||||
*/
|
||||
async function loadDepsFor(sections: DependencySections, parentCompiler: SectionCompiler, source: LDMLKeyboardXMLSourceFile, callbacks: TestCompilerCallbacks, dependencies?: typeof SectionCompiler[]) {
|
||||
async function loadDepsFor(sections: DependencySections, parentCompiler: SectionCompiler, source: LDMLKeyboardXMLSourceFile, callbacks: TestCompilerCallbacks, dependencies?: SectionCompilerNew[]) {
|
||||
const parentId = parentCompiler.id;
|
||||
if (!dependencies) {
|
||||
// default dependencies
|
||||
|
|
@ -184,7 +187,11 @@ export interface CompilationCase {
|
|||
/**
|
||||
* Optional dependent sections to load. Will be strs+list+elem if falsy.
|
||||
*/
|
||||
dependencies?: (typeof SectionCompiler)[];
|
||||
dependencies?: (SectionCompilerNew)[];
|
||||
/**
|
||||
* Optional, if true, postValidate() must return false. (must be != postValidate())
|
||||
*/
|
||||
postValidateFail?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -193,7 +200,7 @@ export interface CompilationCase {
|
|||
* @param compiler argument to loadSectionFixture()
|
||||
* @param callbacks argument to loadSectionFixture()
|
||||
*/
|
||||
export function testCompilationCases(compiler: typeof SectionCompiler, cases : CompilationCase[], dependencies?: (typeof SectionCompiler)[]) {
|
||||
export function testCompilationCases(compiler: SectionCompilerNew, cases : CompilationCase[], dependencies?: (SectionCompilerNew)[]) {
|
||||
// we need our own callbacks rather than using the global so messages don't get mixed
|
||||
const callbacks = new TestCompilerCallbacks();
|
||||
for (let testcase of cases) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue