import { ParsingError } from '../errors/parsing_error'; import { ParserTypings } from '../parser/types_parser'; import { Validation } from './validation_types'; import { ErrorBuilder } from './error_builder'; import { createDefaultValidators } from './default_validators'; /** @mutates */ const mergeOptions = ( target: Required, partial: Validation.ValidationOptions ) => { const keys = Object.keys(partial) as Array< keyof Validation.ValidationOptions >; keys.forEach(key => { if (key === 'getErrorText') { target[key] = partial[key]!; } else if (Array.isArray(target[key])) { target[key] = [...target[key], ...partial[key]!]; } }); }; export class Validator { public errors: ParsingError[] = []; public options: Required = createDefaultValidators(); private errorBuilder = new ErrorBuilder(); constructor(options: Validation.ValidationOptions = {}) { this.mergeOptions(options); } private mergeOptions(partial: Validation.ValidationOptions) { mergeOptions(this.options, partial); this.errorBuilder.getErrorText = this.options.getErrorText; return this; } public validate(parser: ParserTypings.Parser): this { this.options.preValidators.forEach(validator => { try { validator(parser, this.errorBuilder); } catch (beforeError) { this.errors.push(beforeError); } }); for (const [parsingLineNumber, entry] of parser.parsingMeta) { this.errorBuilder.update(parsingLineNumber, entry); this.options.loopValidators.forEach(validator => { try { validator(parser, this.errorBuilder); } catch (loopError) { this.errors.push(loopError); } }); } this.errorBuilder.update(0, {} as any); this.options.postValidators.forEach(validator => { try { validator(parser, this.errorBuilder); } catch (afterError) { this.errors.push(afterError); } }); return this; } }