diff --git a/apps/interpreter/src/examples-smoke-test.spec.ts b/apps/interpreter/src/examples-smoke-test.spec.ts index f4dfc2a6..9ad15d22 100644 --- a/apps/interpreter/src/examples-smoke-test.spec.ts +++ b/apps/interpreter/src/examples-smoke-test.spec.ts @@ -19,6 +19,7 @@ import nock from 'nock'; import { type MockInstance, vi } from 'vitest'; import { runAction } from './run-action'; +import { type RunOptions } from './run-options'; // Mock global imports vi.mock('pg', () => { @@ -46,11 +47,13 @@ vi.mock('sqlite3', () => { describe('jv example smoke tests', () => { const baseDir = path.resolve(__dirname, '../../../example/'); - const defaultOptions = { + const defaultOptions: RunOptions = { + pipeline: '.*', env: new Map(), debug: false, debugGranularity: 'minimal', - debugTarget: undefined, + debugTarget: 'all', + parseOnly: false, }; let exitSpy: MockInstance; diff --git a/apps/interpreter/src/index.ts b/apps/interpreter/src/index.ts index c0ca634e..6e784ac2 100644 --- a/apps/interpreter/src/index.ts +++ b/apps/interpreter/src/index.ts @@ -2,7 +2,10 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { DebugGranularityValues } from '@jvalue/jayvee-execution'; +import { + DebugGranularityValues, + DefaultDebugTargetsValue, +} from '@jvalue/jayvee-execution'; import { Command } from 'commander'; import { version as packageJsonVersion } from '../package.json'; @@ -55,7 +58,7 @@ program .option( '-dt, --debug-target ', `Sets the target blocks of the of block debug logging, separated by comma. If not given, all blocks are targeted.`, - undefined, + DefaultDebugTargetsValue, ) .option( '-po, --parse-only', diff --git a/apps/interpreter/src/parse-only.spec.ts b/apps/interpreter/src/parse-only.spec.ts index 01e56427..25eb3c05 100644 --- a/apps/interpreter/src/parse-only.spec.ts +++ b/apps/interpreter/src/parse-only.spec.ts @@ -6,25 +6,19 @@ import fs from 'node:fs'; import path from 'node:path'; import process from 'node:process'; -import { - type RunOptions, - interpretModel, - interpretString, -} from '@jvalue/jayvee-interpreter-lib'; -import { vi } from 'vitest'; +import { type JayveeInterpreter } from '@jvalue/jayvee-interpreter-lib'; import { runAction } from './run-action'; +import { type RunOptions } from './run-options'; -vi.mock('@jvalue/jayvee-interpreter-lib', async () => { - const original: object = await vi.importActual( - '@jvalue/jayvee-interpreter-lib', - ); - return { - ...original, - interpretModel: vi.fn(), - interpretString: vi.fn(), - }; -}); +const interpreterMock: JayveeInterpreter = { + interpretModel: vi.fn(), + interpretFile: vi.fn(), + interpretString: vi.fn(), + parseModel: vi.fn(), +}; + +vi.stubGlobal('DefaultJayveeInterpreter', interpreterMock); describe('Parse Only', () => { const pathToValidModel = path.resolve(__dirname, '../../../example/cars.jv'); @@ -34,16 +28,18 @@ describe('Parse Only', () => { ); const defaultOptions: RunOptions = { + pipeline: '.*', env: new Map(), debug: false, debugGranularity: 'minimal', - debugTarget: undefined, + debugTarget: 'all', + parseOnly: false, }; afterEach(() => { // Assert that model is not executed - expect(interpretString).not.toBeCalled(); - expect(interpretModel).not.toBeCalled(); + expect(interpreterMock.interpretString).not.toBeCalled(); + expect(interpreterMock.interpretModel).not.toBeCalled(); }); beforeEach(() => { diff --git a/apps/interpreter/src/run-action.ts b/apps/interpreter/src/run-action.ts index a461f53f..cbee97be 100644 --- a/apps/interpreter/src/run-action.ts +++ b/apps/interpreter/src/run-action.ts @@ -5,35 +5,63 @@ import process from 'node:process'; import { - type LoggerFactory, - type RunOptions, + DefaultJayveeInterpreter, + ExitCode, + type JayveeInterpreter, + LoggerFactory, extractAstNodeFromFile, - interpretModel, - parseModel, } from '@jvalue/jayvee-interpreter-lib'; import { type JayveeModel, type JayveeServices, } from '@jvalue/jayvee-language-server'; +import { parsePipelineMatcherRegExp, parseRunOptions } from './run-options'; + export async function runAction( - fileName: string, - options: RunOptions, + filePath: string, + optionsRaw: unknown, ): Promise { - const extractAstNodeFn = async ( - services: JayveeServices, - loggerFactory: LoggerFactory, - ) => - await extractAstNodeFromFile( - fileName, - services, - loggerFactory.createLogger(), - ); + const logger = new LoggerFactory(true).createLogger('Arguments'); + const options = parseRunOptions(optionsRaw, logger); + if (options === undefined) { + return process.exit(ExitCode.FAILURE); + } + + const pipelineRegExp = parsePipelineMatcherRegExp(options.pipeline, logger); + if (pipelineRegExp === undefined) { + return process.exit(ExitCode.FAILURE); + } + + const interpreter = new DefaultJayveeInterpreter({ + pipelineMatcher: (pipelineDefinition) => + pipelineRegExp.test(pipelineDefinition.name), + env: options.env, + debug: options.debug, + debugGranularity: options.debugGranularity, + debugTarget: options.debugTarget, + }); + if (options.parseOnly === true) { - const { model, services } = await parseModel(extractAstNodeFn, options); - const exitCode = model != null && services != null ? 0 : 1; - process.exit(exitCode); + return await runParseOnly(filePath, interpreter); } - const exitCode = await interpretModel(extractAstNodeFn, options); + + const exitCode = await interpreter.interpretFile(filePath); + process.exit(exitCode); +} + +async function runParseOnly( + filePath: string, + interpreter: JayveeInterpreter, +): Promise { + const model = await interpreter.parseModel( + async (services: JayveeServices, loggerFactory: LoggerFactory) => + await extractAstNodeFromFile( + filePath, + services, + loggerFactory.createLogger(), + ), + ); + const exitCode = model === undefined ? ExitCode.FAILURE : ExitCode.SUCCESS; process.exit(exitCode); } diff --git a/apps/interpreter/src/run-options.ts b/apps/interpreter/src/run-options.ts new file mode 100644 index 00000000..b547bc06 --- /dev/null +++ b/apps/interpreter/src/run-options.ts @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { + type DebugGranularity, + DebugGranularityValues, + type DebugTargets, + DefaultDebugTargetsValue, + type Logger, + isDebugGranularity, +} from '@jvalue/jayvee-execution'; + +export interface RunOptions { + pipeline: string; + env: Map; + debug: boolean; + debugGranularity: DebugGranularity; + debugTarget: DebugTargets; + parseOnly: boolean; +} + +export function parseRunOptions( + optionsRaw: unknown, + logger: Logger, +): RunOptions | undefined { + if (typeof optionsRaw !== 'object' || optionsRaw == null) { + logger.logErr( + "Error in the interpreter: didn't receive a valid RunOptions object.", + ); + return undefined; + } + + const requiredFields = [ + 'pipeline', + 'env', + 'debug', + 'debugGranularity', + 'debugTarget', + 'parseOnly', + ]; + if (requiredFields.some((f) => !(f in optionsRaw))) { + logger.logErr( + `Error in the interpreter: didn't receive a valid RunOptions object. Must have the fields ${requiredFields + .map((f) => `"${f}"`) + .join(', ')} but got object ${JSON.stringify(optionsRaw, null, 2)}`, + ); + return undefined; + } + + const options = optionsRaw as Record; + + if ( + !isPipelineArgument(options.pipeline, logger) || + !isEnvArgument(options.env, logger) || + !isDebugArgument(options.debug, logger) || + !isDebugGranularityArgument(options.debugGranularity, logger) || + !isDebugTargetArgument(options.debugTarget, logger) || + !isParseOnlyArgument(options.parseOnly, logger) + ) { + return undefined; + } + + return { + pipeline: options.pipeline, + env: options.env, + debug: options.debug === true || options.debug === 'true', + debugGranularity: options.debugGranularity as DebugGranularity, + debugTarget: getDebugTargets(options.debugTarget), + parseOnly: options.parseOnly === true || options.parseOnly === 'true', + }; +} + +function getDebugTargets(debugTargetsString: string): DebugTargets { + const areAllBlocksTargeted = debugTargetsString === DefaultDebugTargetsValue; + if (areAllBlocksTargeted) { + return DefaultDebugTargetsValue; + } + + return debugTargetsString.split(',').map((target) => target.trim()); +} + +function isPipelineArgument(arg: unknown, logger: Logger): arg is string { + if (typeof arg !== 'string') { + logger.logErr( + `Invalid value "${JSON.stringify( + arg, + )}" for pipeline selection option: -p --pipeline.\n` + + 'Must be a string value.', + ); + return false; + } + return true; +} + +function isDebugGranularityArgument( + arg: unknown, + logger: Logger, +): arg is DebugGranularity { + if (!isDebugGranularity(arg)) { + logger.logErr( + `Invalid value "${JSON.stringify( + arg, + )}" for debug granularity option: -dg --debug-granularity.\n` + + `Must be one of the following values: ${DebugGranularityValues.join( + ', ', + )}.`, + ); + return false; + } + return true; +} + +function isDebugTargetArgument(arg: unknown, logger: Logger): arg is string { + // options.debugTarget + if (typeof arg !== 'string') { + logger.logErr( + `Invalid value "${JSON.stringify( + arg, + )}" for debug target option: -dt --debug-target.\n` + + 'Must be a string value.', + ); + return false; + } + return true; +} + +function isDebugArgument( + arg: unknown, + logger: Logger, +): arg is boolean | 'true' | 'false' { + if (typeof arg !== 'boolean' && arg !== 'true' && arg !== 'false') { + logger.logErr( + `Invalid value "${JSON.stringify(arg)}" for debug option: -d --debug.\n` + + 'Must be true or false.', + ); + return false; + } + return true; +} + +function isParseOnlyArgument( + arg: unknown, + logger: Logger, +): arg is boolean | 'true' | 'false' { + if (typeof arg !== 'boolean' && arg !== 'true' && arg !== 'false') { + logger.logErr( + `Invalid value "${JSON.stringify( + arg, + )}" for parse-only option: -po --parse-only.\n` + + 'Must be true or false.', + ); + return false; + } + return true; +} + +function isEnvArgument( + arg: unknown, + logger: Logger, +): arg is Map { + if ( + !( + arg instanceof Map && + [...arg.entries()].every( + ([key, value]) => typeof key === 'string' && typeof value === 'string', + ) + ) + ) { + logger.logErr( + `Invalid value "${JSON.stringify(arg)}" for env option: -e --env.\n` + + 'Must be map from string keys to string values.', + ); + return false; + } + return true; +} + +export function parsePipelineMatcherRegExp( + matcher: string, + logger: Logger, +): RegExp | undefined { + try { + return new RegExp(matcher); + } catch (e: unknown) { + logger.logErr( + `Invalid value "${matcher}" for pipeline selection option: -p --pipeline.\n` + + 'Must be a valid regular expression.', + ); + return undefined; + } +} diff --git a/libs/interpreter-lib/src/interpreter.spec.ts b/libs/interpreter-lib/src/interpreter.spec.ts index 21693721..08a534a2 100644 --- a/libs/interpreter-lib/src/interpreter.spec.ts +++ b/libs/interpreter-lib/src/interpreter.spec.ts @@ -4,7 +4,7 @@ import { readJvTestAssetHelper } from '@jvalue/jayvee-language-server/test'; -import { interpretString } from './interpreter'; +import { DefaultJayveeInterpreter } from './interpreter'; import { ExitCode } from './parsing-util'; describe('Interpreter', () => { @@ -15,12 +15,14 @@ describe('Interpreter', () => { const exampleFilePath = 'example/cars.jv'; const model = readJvTestAsset(exampleFilePath); - const exitCode = await interpretString(model, { + const interpreter = new DefaultJayveeInterpreter({ + pipelineMatcher: () => true, debug: true, debugGranularity: 'peek', - debugTarget: undefined, + debugTarget: 'all', env: new Map(), }); + const exitCode = await interpreter.interpretString(model); expect(exitCode).toEqual(ExitCode.SUCCESS); }); }); diff --git a/libs/interpreter-lib/src/interpreter.ts b/libs/interpreter-lib/src/interpreter.ts index 64fc1343..21f46000 100644 --- a/libs/interpreter-lib/src/interpreter.ts +++ b/libs/interpreter-lib/src/interpreter.ts @@ -5,16 +5,16 @@ // eslint-disable-next-line unicorn/prefer-node-protocol import { strict as assert } from 'assert'; -import * as R from '@jvalue/jayvee-execution'; import { type DebugGranularity, + type DebugTargets, DefaultConstraintExtension, ExecutionContext, type JayveeConstraintExtension, type JayveeExecExtension, type Logger, executeBlocks, - isDebugGranularity, + isErr, logExecutionDuration, parseValueToInternalRepresentation, } from '@jvalue/jayvee-execution'; @@ -34,267 +34,246 @@ import chalk from 'chalk'; import { NodeFileSystem } from 'langium/node'; import { LoggerFactory } from './logging'; -import { ExitCode, extractAstNodeFromString } from './parsing-util'; +import { + ExitCode, + extractAstNodeFromFile, + extractAstNodeFromString, +} from './parsing-util'; import { validateRuntimeParameterLiteral } from './validation-checks'; -interface InterpreterOptions { +export interface InterpreterOptions { pipelineMatcher: (pipelineDefinition: PipelineDefinition) => boolean; - debugGranularity: R.DebugGranularity; - debugTargets: R.DebugTargets; - debug: boolean; -} - -export interface RunOptions { - pipeline: string; env: Map; debug: boolean; - debugGranularity: string; - debugTarget: string | undefined; - parseOnly?: boolean; + debugGranularity: DebugGranularity; + debugTarget: DebugTargets; } -export async function interpretString( - modelString: string, - options: RunOptions, -): Promise { - const extractAstNodeFn = async ( - services: JayveeServices, - loggerFactory: LoggerFactory, - ) => - await extractAstNodeFromString( - modelString, - services, - loggerFactory.createLogger(), - ); - return await interpretModel(extractAstNodeFn, options); +export interface JayveeInterpreter { + /** + * Interprets a parsed Jayvee model. + * + * @param extractAstNodeFn the Jayvee model. + * @returns the exit code indicating whether interpretation was successful or not. + */ + interpretModel(model: JayveeModel): Promise; + + /** + * Interprets a file as a Jayvee model. + * Parses the file first as a Jayvee model. + * + * @param filePath the file path to the Jayvee model. + * @returns the exit code indicating whether interpretation was successful or not. + */ + interpretFile(filePath: string): Promise; + + /** + * Interprets a string as a Jayvee model. + * Parses the string first as a Jayvee model. + * + * @param modelString the Jayvee model string. + * @returns the exit code indicating whether interpretation was successful or not. + */ + interpretString(modelString: string): Promise; + + /** + * Parses a model without executing it. + * Also sets up the environment so that the model can be properly executed. + * + * @param extractAstNodeFn method that extracts the AST node; should also initialize the workspace correctly. + * @returns the parsed Jayvee model, or undefined on failure. + */ + parseModel( + extractAstNodeFn: ( + services: JayveeServices, + loggerFactory: LoggerFactory, + ) => Promise, + ): Promise; } -/** - * Parses a model without executing it. - * Also sets up the environment so that the model can be properly executed. - * - * @param extractAstNodeFn method that extracts the AST node; should also initialize the workspace correctly. - * @returns non-null model, services and loggerFactory on success. - */ -export async function parseModel( - extractAstNodeFn: ( - services: JayveeServices, - loggerFactory: LoggerFactory, - ) => Promise, - options: RunOptions, -): Promise<{ - model: JayveeModel | null; - loggerFactory: LoggerFactory; - services: JayveeServices | null; -}> { - let services: JayveeServices | null = null; - let model: JayveeModel | null = null; - const loggerFactory = new LoggerFactory(options.debug); - if (!isDebugGranularity(options.debugGranularity)) { - loggerFactory - .createLogger() - .logErr( - `Unknown value "${options.debugGranularity}" for debug granularity option: -dg --debug-granularity.\n` + - `Please use one of the following values: ${R.DebugGranularityValues.join( - ', ', - )}.`, - ); - return { model, services, loggerFactory }; - } +export class DefaultJayveeInterpreter implements JayveeInterpreter { + private readonly services: JayveeServices; + private readonly loggerFactory: LoggerFactory; - services = createJayveeServices(NodeFileSystem).Jayvee; - setupJayveeServices(services, options.env); + constructor(private readonly options: InterpreterOptions) { + this.services = createJayveeServices(NodeFileSystem).Jayvee; + this.setupJayveeServices(this.services, this.options.env); - try { - model = await extractAstNodeFn(services, loggerFactory); - return { model, services, loggerFactory }; - } catch (e) { - loggerFactory - .createLogger() - .logErr('Could not extract the AST node of the given model.'); - return { model, services, loggerFactory }; + this.loggerFactory = new LoggerFactory(options.debug); } -} -export async function interpretModel( - extractAstNodeFn: ( - services: JayveeServices, - loggerFactory: LoggerFactory, - ) => Promise, - options: RunOptions, -): Promise { - const { model, services, loggerFactory } = await parseModel( - extractAstNodeFn, - options, - ); + async interpretModel(model: JayveeModel): Promise { + const interpretationExitCode = await this.interpretJayveeModel( + model, + new StdExecExtension(), + new DefaultConstraintExtension(), + ); + return interpretationExitCode; + } - const interpreterLogger = loggerFactory.createLogger('Interpreter'); + async interpretFile(filePath: string): Promise { + const extractAstNodeFn = async ( + services: JayveeServices, + loggerFactory: LoggerFactory, + ) => + await extractAstNodeFromFile( + filePath, + services, + loggerFactory.createLogger(), + ); - const pipelineMatcherRegexp = parsePipelineMatcher( - options.pipeline, - interpreterLogger, - ); + const model = await this.parseModel(extractAstNodeFn); + if (model === undefined) { + return ExitCode.FAILURE; + } - if ( - model == null || - services == null || - pipelineMatcherRegexp === undefined - ) { - return ExitCode.FAILURE; + return await this.interpretModel(model); } - const debugTargets = getDebugTargets(options.debugTarget); - - const interpretationExitCode = await interpretJayveeModel( - model, - new StdExecExtension(), - new DefaultConstraintExtension(), - services, - loggerFactory, - interpreterLogger, - { - pipelineMatcher: (pipelineDefinition) => - pipelineMatcherRegexp.test(pipelineDefinition.name), - debug: options.debug, - // type of options.debugGranularity is asserted in parseModel - debugGranularity: options.debugGranularity as DebugGranularity, - debugTargets: debugTargets, - }, - ); - return interpretationExitCode; -} + async interpretString(modelString: string): Promise { + const extractAstNodeFn = async ( + services: JayveeServices, + loggerFactory: LoggerFactory, + ) => + await extractAstNodeFromString( + modelString, + services, + loggerFactory.createLogger(), + ); -function parsePipelineMatcher( - matcherString: string, - logger: Logger, -): RegExp | undefined { - try { - return new RegExp(matcherString); - } catch (e: unknown) { - logger.logErr( - `Given pipeline matcher argument is not valid: "${matcherString}" is no valid regular expression${ - e instanceof SyntaxError ? `: ${e.message}` : '' - }`, - ); - } - return undefined; -} + const model = await this.parseModel(extractAstNodeFn); + if (model === undefined) { + return ExitCode.FAILURE; + } -function setupJayveeServices( - services: JayveeServices, - rawRuntimeParameters: ReadonlyMap, -) { - setupRuntimeParameterProvider( - services.RuntimeParameterProvider, - rawRuntimeParameters, - ); + return await this.interpretModel(model); + } - services.validation.ValidationRegistry.registerJayveeValidationChecks({ - RuntimeParameterLiteral: validateRuntimeParameterLiteral, - }); -} + async parseModel( + extractAstNodeFn: ( + services: JayveeServices, + loggerFactory: LoggerFactory, + ) => Promise, + ): Promise { + try { + const model = await extractAstNodeFn(this.services, this.loggerFactory); + return model; + } catch (e) { + this.loggerFactory + .createLogger() + .logErr('Could not extract the AST node of the given model.'); + return undefined; + } + } -function setupRuntimeParameterProvider( - runtimeParameterProvider: RuntimeParameterProvider, - rawRuntimeParameters: ReadonlyMap, -) { - runtimeParameterProvider.setValueParser(parseValueToInternalRepresentation); + private setupJayveeServices( + services: JayveeServices, + rawRuntimeParameters: ReadonlyMap, + ) { + this.setupRuntimeParameterProvider( + services.RuntimeParameterProvider, + rawRuntimeParameters, + ); - for (const [key, value] of rawRuntimeParameters.entries()) { - runtimeParameterProvider.setValue(key, value); + services.validation.ValidationRegistry.registerJayveeValidationChecks({ + RuntimeParameterLiteral: validateRuntimeParameterLiteral, + }); } -} -async function interpretJayveeModel( - model: JayveeModel, - executionExtension: JayveeExecExtension, - constraintExtension: JayveeConstraintExtension, - jayveeServices: JayveeServices, - loggerFactory: LoggerFactory, - interpreterLogger: Logger, - runOptions: InterpreterOptions, -): Promise { - const selectedPipelines = model.pipelines.filter((pipeline) => - runOptions.pipelineMatcher(pipeline), - ); - interpreterLogger.logInfo( - `Found ${selectedPipelines.length} pipelines to execute${ - selectedPipelines.length > 0 - ? ': ' + selectedPipelines.map((p) => p.name).join(', ') - : '' - }`, - ); + private setupRuntimeParameterProvider( + runtimeParameterProvider: RuntimeParameterProvider, + rawRuntimeParameters: ReadonlyMap, + ) { + runtimeParameterProvider.setValueParser(parseValueToInternalRepresentation); - const pipelineRuns: Promise[] = selectedPipelines.map( - (pipeline) => { - return runPipeline( - pipeline, - executionExtension, - constraintExtension, - jayveeServices, - loggerFactory, - runOptions, + for (const [key, value] of rawRuntimeParameters.entries()) { + runtimeParameterProvider.setValue(key, value); + } + } + + private async interpretJayveeModel( + model: JayveeModel, + executionExtension: JayveeExecExtension, + constraintExtension: JayveeConstraintExtension, + ): Promise { + const selectedPipelines = model.pipelines.filter((pipeline) => + this.options.pipelineMatcher(pipeline), + ); + this.loggerFactory + .createLogger() + .logInfo( + `Found ${selectedPipelines.length} pipelines to execute${ + selectedPipelines.length > 0 + ? ': ' + selectedPipelines.map((p) => p.name).join(', ') + : '' + }`, ); - }, - ); - const exitCodes = await Promise.all(pipelineRuns); - if (exitCodes.includes(ExitCode.FAILURE)) { - return ExitCode.FAILURE; + const pipelineRuns: Promise[] = selectedPipelines.map( + (pipeline) => { + return this.runPipeline( + pipeline, + executionExtension, + constraintExtension, + ); + }, + ); + const exitCodes = await Promise.all(pipelineRuns); + + if (exitCodes.includes(ExitCode.FAILURE)) { + return ExitCode.FAILURE; + } + return ExitCode.SUCCESS; } - return ExitCode.SUCCESS; -} -async function runPipeline( - pipeline: PipelineDefinition, - executionExtension: JayveeExecExtension, - constraintExtension: JayveeConstraintExtension, - jayveeServices: JayveeServices, - loggerFactory: LoggerFactory, - runOptions: InterpreterOptions, -): Promise { - const executionContext = new ExecutionContext( - pipeline, - executionExtension, - constraintExtension, - loggerFactory.createLogger(), - jayveeServices.WrapperFactories, - jayveeServices.ValueTypeProvider, - { - isDebugMode: runOptions.debug, - debugGranularity: runOptions.debugGranularity, - debugTargets: runOptions.debugTargets, - }, - new EvaluationContext( - jayveeServices.RuntimeParameterProvider, - jayveeServices.operators.EvaluatorRegistry, - jayveeServices.ValueTypeProvider, - ), - ); + private async runPipeline( + pipeline: PipelineDefinition, + executionExtension: JayveeExecExtension, + constraintExtension: JayveeConstraintExtension, + ): Promise { + const executionContext = new ExecutionContext( + pipeline, + executionExtension, + constraintExtension, + this.loggerFactory.createLogger(), + this.services.WrapperFactories, + this.services.ValueTypeProvider, + { + isDebugMode: this.options.debug, + debugGranularity: this.options.debugGranularity, + debugTargets: this.options.debugTarget, + }, + new EvaluationContext( + this.services.RuntimeParameterProvider, + this.services.operators.EvaluatorRegistry, + this.services.ValueTypeProvider, + ), + ); - logPipelineOverview( - pipeline, - jayveeServices.RuntimeParameterProvider, - executionContext.logger, - jayveeServices.WrapperFactories, - ); + logPipelineOverview( + pipeline, + this.services.RuntimeParameterProvider, + executionContext.logger, + this.services.WrapperFactories, + ); - const startTime = new Date(); + const startTime = new Date(); - const executionResult = await executeBlocks(executionContext, pipeline); + const executionResult = await executeBlocks(executionContext, pipeline); + + if (isErr(executionResult)) { + const diagnosticError = executionResult.left; + executionContext.logger.logErrDiagnostic( + diagnosticError.message, + diagnosticError.diagnostic, + ); + logExecutionDuration(startTime, executionContext.logger); + return ExitCode.FAILURE; + } - if (R.isErr(executionResult)) { - const diagnosticError = executionResult.left; - executionContext.logger.logErrDiagnostic( - diagnosticError.message, - diagnosticError.diagnostic, - ); logExecutionDuration(startTime, executionContext.logger); - return ExitCode.FAILURE; + return ExitCode.SUCCESS; } - - logExecutionDuration(startTime, executionContext.logger); - return ExitCode.SUCCESS; } export function logPipelineOverview( @@ -339,14 +318,3 @@ export function logPipelineOverview( } logger.logInfo(linesBuffer.join('\n')); } - -function getDebugTargets( - debugTargetsString: string | undefined, -): R.DebugTargets { - const areAllBlocksTargeted = debugTargetsString === undefined; - if (areAllBlocksTargeted) { - return R.DefaultDebugTargetsValue; - } - - return debugTargetsString.split(',').map((target) => target.trim()); -} diff --git a/libs/interpreter-lib/src/parsing-util.ts b/libs/interpreter-lib/src/parsing-util.ts index 7d6ab2d2..4f100b53 100644 --- a/libs/interpreter-lib/src/parsing-util.ts +++ b/libs/interpreter-lib/src/parsing-util.ts @@ -22,12 +22,12 @@ export enum ExitCode { * Does load the directory of this document as the working directory. */ export async function extractDocumentFromFile( - fileName: string, + filePath: string, services: LangiumServices, logger: Logger, ): Promise { const extensions = services.LanguageMetaData.fileExtensions; - if (!extensions.includes(path.extname(fileName))) { + if (!extensions.includes(path.extname(filePath))) { const errorMessage = `Please choose a file with ${ extensions.length === 1 ? 'this extension' : 'one of these extensions' }: ${extensions.map((extension) => `"${extension}"`).join(',')}`; @@ -36,12 +36,12 @@ export async function extractDocumentFromFile( return Promise.reject(ExitCode.FAILURE); } - if (!fs.existsSync(fileName)) { - logger.logErr(`File ${fileName} does not exist.`); + if (!fs.existsSync(filePath)) { + logger.logErr(`File ${filePath} does not exist.`); return Promise.reject(ExitCode.FAILURE); } - const workingDirPath = path.dirname(fileName); + const workingDirPath = path.dirname(filePath); await initializeWorkspace(services, [ { @@ -51,10 +51,10 @@ export async function extractDocumentFromFile( ]); const document = services.shared.workspace.LangiumDocuments.getDocument( - URI.file(path.resolve(fileName)), + URI.file(path.resolve(filePath)), ); if (document === undefined) { - logger.logErr(`Did not load file ${fileName} correctly.`); + logger.logErr(`Did not load file ${filePath} correctly.`); return Promise.reject(ExitCode.FAILURE); } @@ -112,11 +112,11 @@ export async function validateDocument( } export async function extractAstNodeFromFile( - fileName: string, + filePath: string, services: LangiumServices, logger: Logger, ): Promise { - return (await extractDocumentFromFile(fileName, services, logger)).parseResult + return (await extractDocumentFromFile(filePath, services, logger)).parseResult .value as T; }