UNPKG

typir

Version:

General purpose type checking library

125 lines 12 kB
/****************************************************************************** * Copyright 2024 TypeFox GmbH * This program and the accompanying materials are made available under the * terms of the MIT License, which is available in the project root. ******************************************************************************/ import { Type } from '../graph/type-node.js'; import { TypirSpecifics, TypirServices, MakePropertyOptional } from '../typir.js'; import { RuleCollectorListener, RuleOptions, RuleRegistry } from '../utils/rule-registration.js'; import { TypirProblem } from '../utils/utils-definitions.js'; import { TypeCheckStrategy } from '../utils/utils-type-comparison.js'; import { TypeInferenceCollector } from './inference.js'; import { ProblemPrinter } from './printing.js'; export type Severity = 'error' | 'warning' | 'info' | 'hint'; export interface ValidationMessageProperties { severity: Severity; message: string; subProblems?: TypirProblem[]; } export type ValidationProblem<Specifics extends TypirSpecifics, T extends Specifics['LanguageType'] = Specifics['LanguageType']> = ValidationProblemProperties<Specifics, T> & TypirProblem & { $problem: 'ValidationProblem'; }; export declare const ValidationProblem = "ValidationProblem"; export declare function isValidationProblem<Specifics extends TypirSpecifics, T extends Specifics['LanguageType'] = Specifics['LanguageType']>(problem: unknown): problem is ValidationProblem<Specifics, T>; export type ValidationProblemProperties<Specifics extends TypirSpecifics, T extends Specifics['LanguageType'] = Specifics['LanguageType']> = Specifics['ValidationMessageProperties'] & { languageNode: T; languageProperty?: string; languageIndex?: number; }; /** Make some properties optional for convenience, since there are default values for them. */ export type RelaxedValidationProblem<Specifics extends TypirSpecifics, T extends Specifics['LanguageType'] = Specifics['LanguageType']> = MakePropertyOptional<ValidationProblemProperties<Specifics, T>, 'languageNode' | 'severity' | 'message'>; export type ValidationProblemAcceptor<Specifics extends TypirSpecifics> = <T extends Specifics['LanguageType'] = Specifics['LanguageType']>(problem: ValidationProblemProperties<Specifics, T>) => void; export type ValidationRule<Specifics extends TypirSpecifics, InputType extends Specifics['LanguageType'] = Specifics['LanguageType']> = ValidationRuleFunctional<Specifics, InputType> | ValidationRuleLifecycle<Specifics, Specifics['LanguageType'], InputType>; /** * Describes a simple, state-less validation rule, * which might produce an unlimited number of problems. */ export type ValidationRuleFunctional<Specifics extends TypirSpecifics, InputType extends Specifics['LanguageType'] = Specifics['LanguageType']> = (languageNode: InputType, accept: ValidationProblemAcceptor<Specifics>, typir: TypirServices<Specifics>) => void; /** * Describes a complex validation rule which has a state. * 'beforeValidation' can be used to set-up some data structures like a map, * in order to store some information which are calculated during 'validation', * which are finally evaluated in 'afterValidation'. */ export interface ValidationRuleLifecycle<Specifics extends TypirSpecifics, RootType extends Specifics['LanguageType'] = Specifics['LanguageType'], InputType extends Specifics['LanguageType'] = Specifics['LanguageType']> { beforeValidation?: (languageRoot: RootType, accept: ValidationProblemAcceptor<Specifics>, typir: TypirServices<Specifics>) => void; validation: ValidationRuleFunctional<Specifics, InputType>; afterValidation?: (languageRoot: RootType, accept: ValidationProblemAcceptor<Specifics>, typir: TypirServices<Specifics>) => void; } /** Annotate types after the validation with additional information in order to ease the creation of usefull messages. */ export interface AnnotatedTypeAfterValidation { type: Type; userRepresentation: string; name: string; } export type ValidationMessageProvider<Specifics extends TypirSpecifics, T extends Specifics['LanguageType'] = Specifics['LanguageType']> = (actual: AnnotatedTypeAfterValidation, expected: AnnotatedTypeAfterValidation) => RelaxedValidationProblem<Specifics, T>; export interface ValidationConstraints<Specifics extends TypirSpecifics> { ensureNodeIsAssignable<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, expected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeIsEquals<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, expected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeHasNotType<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, notExpected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeRelatedWithType<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(languageNode: S | undefined, expected: Type | undefined | E, strategy: TypeCheckStrategy, negated: boolean, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; } export declare class DefaultValidationConstraints<Specifics extends TypirSpecifics> implements ValidationConstraints<Specifics> { protected readonly services: TypirServices<Specifics>; protected readonly inference: TypeInferenceCollector<Specifics>; protected readonly printer: ProblemPrinter<Specifics>; constructor(services: TypirServices<Specifics>); ensureNodeIsAssignable<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, expected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeIsEquals<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, expected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeHasNotType<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(sourceNode: S | undefined, notExpected: Type | undefined | E, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; ensureNodeRelatedWithType<S extends Specifics['LanguageType'], E extends Specifics['LanguageType'], T extends Specifics['LanguageType'] = Specifics['LanguageType']>(languageNode: S | undefined, expected: Type | undefined | E, strategy: TypeCheckStrategy, negated: boolean, accept: ValidationProblemAcceptor<Specifics>, message: ValidationMessageProvider<Specifics, T>): void; protected annotateType(type: Type): AnnotatedTypeAfterValidation; } export interface ValidationCollectorListener<Specifics extends TypirSpecifics> { onAddedValidationRule(rule: ValidationRule<Specifics>, options: ValidationRuleOptions): void; onRemovedValidationRule(rule: ValidationRule<Specifics>, options: ValidationRuleOptions): void; } export interface ValidationRuleOptions extends RuleOptions { } export interface ValidationCollector<Specifics extends TypirSpecifics> { validateBefore(languageNode: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; validate(languageNode: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; validateAfter(languageNode: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; /** * Registers a validation rule. * @param rule a new validation rule * @param options some more options to control the handling of the added validation rule */ addValidationRule<InputType extends Specifics['LanguageType'] = Specifics['LanguageType']>(rule: ValidationRule<Specifics, InputType>, options?: Partial<ValidationRuleOptions>): void; /** * Removes a validation rule. * @param rule the validation rule to remove * @param options the same options as given for the registration of the validation rule must be given for the removal! */ removeValidationRule<InputType extends Specifics['LanguageType'] = Specifics['LanguageType']>(rule: ValidationRule<Specifics, InputType>, options?: Partial<ValidationRuleOptions>): void; addListener(listener: ValidationCollectorListener<Specifics>): void; removeListener(listener: ValidationCollectorListener<Specifics>): void; } export declare class DefaultValidationCollector<Specifics extends TypirSpecifics> implements ValidationCollector<Specifics>, RuleCollectorListener<ValidationRule<Specifics>> { protected readonly services: TypirServices<Specifics>; protected readonly listeners: Array<ValidationCollectorListener<Specifics>>; protected readonly ruleRegistryFunctional: RuleRegistry<ValidationRuleFunctional<Specifics>, Specifics>; protected readonly ruleRegistryLifecycle: RuleRegistry<ValidationRuleLifecycle<Specifics>, Specifics>; constructor(services: TypirServices<Specifics>); protected createAcceptor(problems: Array<ValidationProblem<Specifics>>): ValidationProblemAcceptor<Specifics>; validateBefore(languageRoot: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; validate(languageNode: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; validateAfter(languageRoot: Specifics['LanguageType']): Array<ValidationProblem<Specifics>>; addValidationRule<InputType extends Specifics['LanguageType'] = Specifics['LanguageType']>(rule: ValidationRule<Specifics, InputType>, givenOptions?: Partial<ValidationRuleOptions>): void; removeValidationRule<InputType extends Specifics['LanguageType'] = Specifics['LanguageType']>(rule: ValidationRule<Specifics, InputType>, givenOptions?: Partial<ValidationRuleOptions>): void; addListener(listener: ValidationCollectorListener<Specifics>): void; removeListener(listener: ValidationCollectorListener<Specifics>): void; onAddedRule(rule: ValidationRule<Specifics>, diffOptions: RuleOptions): void; onRemovedRule(rule: ValidationRule<Specifics>, diffOptions: RuleOptions): void; } export declare class CompositeValidationRule<Specifics extends TypirSpecifics> extends DefaultValidationCollector<Specifics> implements ValidationRuleLifecycle<Specifics> { /** The collector for inference rules, at which this composite rule should be registered. */ protected readonly collectorToRegisterThisRule: ValidationCollector<Specifics>; constructor(services: TypirServices<Specifics>, collectorToRegisterThisRule: ValidationCollector<Specifics>); beforeValidation(languageRoot: Specifics['LanguageType'], accept: ValidationProblemAcceptor<Specifics>, _typir: TypirServices<Specifics>): void; validation(languageNode: Specifics['LanguageType'], accept: ValidationProblemAcceptor<Specifics>, _typir: TypirServices<Specifics>): void; afterValidation(languageRoot: Specifics['LanguageType'], accept: ValidationProblemAcceptor<Specifics>, _typir: TypirServices<Specifics>): void; onAddedRule(rule: ValidationRule<Specifics>, diffOptions: RuleOptions): void; onRemovedRule(rule: ValidationRule<Specifics>, diffOptions: RuleOptions): void; } //# sourceMappingURL=validation.d.ts.map