Add validation for max line length in compiler
This commit adds validation logic in compiler to check for max allowed characters per line for scripts. This allows preventing bugs caused by limitation of terminal emulators. Other supporting changes: - Rename/refactor related code for clarity and better maintainability. - Drop `I` prefix from interfaces to align with latest convention. - Refactor CodeValidator to be functional rather than object-oriented for simplicity. - Refactor syntax definition construction to be functional and be part of rule for better separation of concerns. - Refactored validation logic to use an enum-based factory pattern for improved maintainability and scalability.
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
import type { ScriptData, CodeScriptData, CallScriptData } from '@/application/collections/';
|
||||
import { NoEmptyLines } from '@/application/Parser/Executable/Script/Validation/Rules/NoEmptyLines';
|
||||
import type { ILanguageSyntax } from '@/application/Parser/Executable/Script/Validation/Syntax/ILanguageSyntax';
|
||||
import { RecommendationLevel } from '@/domain/Executables/Script/RecommendationLevel';
|
||||
import type { ScriptCode } from '@/domain/Executables/Script/Code/ScriptCode';
|
||||
import type { ICodeValidator } from '@/application/Parser/Executable/Script/Validation/ICodeValidator';
|
||||
import { validateCode, type CodeValidator } from '@/application/Parser/Executable/Script/Validation/CodeValidator';
|
||||
import { wrapErrorWithAdditionalContext, type ErrorWithContextWrapper } from '@/application/Parser/Common/ContextualError';
|
||||
import type { ScriptCodeFactory } from '@/domain/Executables/Script/Code/ScriptCodeFactory';
|
||||
import { createScriptCode } from '@/domain/Executables/Script/Code/ScriptCodeFactory';
|
||||
@@ -11,24 +9,24 @@ import type { Script } from '@/domain/Executables/Script/Script';
|
||||
import { createEnumParser, type EnumParser } from '@/application/Common/Enum';
|
||||
import { filterEmptyStrings } from '@/application/Common/Text/FilterEmptyStrings';
|
||||
import { createScript, type ScriptFactory } from '@/domain/Executables/Script/ScriptFactory';
|
||||
import type { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { CodeValidationRule } from '@/application/Parser/Executable/Script/Validation/CodeValidationRule';
|
||||
import { parseDocs, type DocsParser } from '../DocumentationParser';
|
||||
import { ExecutableType } from '../Validation/ExecutableType';
|
||||
import { createExecutableDataValidator, type ExecutableValidator, type ExecutableValidatorFactory } from '../Validation/ExecutableValidator';
|
||||
import { CodeValidator } from './Validation/CodeValidator';
|
||||
import { NoDuplicatedLines } from './Validation/Rules/NoDuplicatedLines';
|
||||
import type { CategoryCollectionSpecificUtilities } from '../CategoryCollectionSpecificUtilities';
|
||||
import type { CategoryCollectionContext } from '../CategoryCollectionContext';
|
||||
|
||||
export interface ScriptParser {
|
||||
(
|
||||
data: ScriptData,
|
||||
collectionUtilities: CategoryCollectionSpecificUtilities,
|
||||
collectionContext: CategoryCollectionContext,
|
||||
scriptUtilities?: ScriptParserUtilities,
|
||||
): Script;
|
||||
}
|
||||
|
||||
export const parseScript: ScriptParser = (
|
||||
data,
|
||||
collectionUtilities,
|
||||
collectionContext,
|
||||
scriptUtilities = DefaultUtilities,
|
||||
) => {
|
||||
const validator = scriptUtilities.createValidator({
|
||||
@@ -42,7 +40,7 @@ export const parseScript: ScriptParser = (
|
||||
name: data.name,
|
||||
code: parseCode(
|
||||
data,
|
||||
collectionUtilities,
|
||||
collectionContext,
|
||||
scriptUtilities.codeValidator,
|
||||
scriptUtilities.createCode,
|
||||
),
|
||||
@@ -70,29 +68,34 @@ function parseLevel(
|
||||
|
||||
function parseCode(
|
||||
script: ScriptData,
|
||||
collectionUtilities: CategoryCollectionSpecificUtilities,
|
||||
codeValidator: ICodeValidator,
|
||||
collectionContext: CategoryCollectionContext,
|
||||
codeValidator: CodeValidator,
|
||||
createCode: ScriptCodeFactory,
|
||||
): ScriptCode {
|
||||
if (collectionUtilities.compiler.canCompile(script)) {
|
||||
return collectionUtilities.compiler.compile(script);
|
||||
if (collectionContext.compiler.canCompile(script)) {
|
||||
return collectionContext.compiler.compile(script);
|
||||
}
|
||||
const codeScript = script as CodeScriptData; // Must be inline code if it cannot be compiled
|
||||
const code = createCode(codeScript.code, codeScript.revertCode);
|
||||
validateHardcodedCodeWithoutCalls(code, codeValidator, collectionUtilities.syntax);
|
||||
validateHardcodedCodeWithoutCalls(code, codeValidator, collectionContext.language);
|
||||
return code;
|
||||
}
|
||||
|
||||
function validateHardcodedCodeWithoutCalls(
|
||||
scriptCode: ScriptCode,
|
||||
validator: ICodeValidator,
|
||||
syntax: ILanguageSyntax,
|
||||
validate: CodeValidator,
|
||||
language: ScriptingLanguage,
|
||||
) {
|
||||
filterEmptyStrings([scriptCode.execute, scriptCode.revert])
|
||||
.forEach(
|
||||
(code) => validator.throwIfInvalid(
|
||||
(code) => validate(
|
||||
code,
|
||||
[new NoEmptyLines(), new NoDuplicatedLines(syntax)],
|
||||
language,
|
||||
[
|
||||
CodeValidationRule.NoEmptyLines,
|
||||
CodeValidationRule.NoDuplicatedLines,
|
||||
CodeValidationRule.NoTooLongLines,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -126,7 +129,7 @@ function validateScript(
|
||||
interface ScriptParserUtilities {
|
||||
readonly levelParser: EnumParser<RecommendationLevel>;
|
||||
readonly createScript: ScriptFactory;
|
||||
readonly codeValidator: ICodeValidator;
|
||||
readonly codeValidator: CodeValidator;
|
||||
readonly wrapError: ErrorWithContextWrapper;
|
||||
readonly createValidator: ExecutableValidatorFactory;
|
||||
readonly createCode: ScriptCodeFactory;
|
||||
@@ -136,7 +139,7 @@ interface ScriptParserUtilities {
|
||||
const DefaultUtilities: ScriptParserUtilities = {
|
||||
levelParser: createEnumParser(RecommendationLevel),
|
||||
createScript,
|
||||
codeValidator: CodeValidator.instance,
|
||||
codeValidator: validateCode,
|
||||
wrapError: wrapErrorWithAdditionalContext,
|
||||
createValidator: createExecutableDataValidator,
|
||||
createCode: createScriptCode,
|
||||
|
||||
Reference in New Issue
Block a user