From 7a17450ca1574e1d7d1d75e33bcb44924312c1c8 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Tue, 14 May 2024 09:56:49 +0200 Subject: [PATCH 01/13] Work whole working directory instead of single file when interpreting a file --- libs/interpreter-lib/src/interpreter.ts | 3 +-- libs/interpreter-lib/src/parsing-util.ts | 28 +++++++++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/libs/interpreter-lib/src/interpreter.ts b/libs/interpreter-lib/src/interpreter.ts index 1d8fb72c3..58d76f454 100644 --- a/libs/interpreter-lib/src/interpreter.ts +++ b/libs/interpreter-lib/src/interpreter.ts @@ -28,7 +28,6 @@ import { type RuntimeParameterProvider, type WrapperFactoryProvider, createJayveeServices, - initializeWorkspace, internalValueToString, } from '@jvalue/jayvee-language-server'; import chalk from 'chalk'; @@ -72,6 +71,7 @@ export async function interpretString( * 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( @@ -101,7 +101,6 @@ export async function parseModel( } services = createJayveeServices(NodeFileSystem).Jayvee; - await initializeWorkspace(services); setupJayveeServices(services, options.env); try { diff --git a/libs/interpreter-lib/src/parsing-util.ts b/libs/interpreter-lib/src/parsing-util.ts index 8edccae71..7d6ab2d2f 100644 --- a/libs/interpreter-lib/src/parsing-util.ts +++ b/libs/interpreter-lib/src/parsing-util.ts @@ -17,6 +17,10 @@ export enum ExitCode { FAILURE = 1, } +/** + * Extracts a document from a file that contains a model. + * Does load the directory of this document as the working directory. + */ export async function extractDocumentFromFile( fileName: string, services: LangiumServices, @@ -37,16 +41,30 @@ export async function extractDocumentFromFile( return Promise.reject(ExitCode.FAILURE); } - const document = - await services.shared.workspace.LangiumDocuments.getOrCreateDocument( - URI.file(path.resolve(fileName)), - ); + const workingDirPath = path.dirname(fileName); - await initializeWorkspace(services); + await initializeWorkspace(services, [ + { + name: 'projectRoot', + uri: path.resolve(workingDirPath), + }, + ]); + + const document = services.shared.workspace.LangiumDocuments.getDocument( + URI.file(path.resolve(fileName)), + ); + if (document === undefined) { + logger.logErr(`Did not load file ${fileName} correctly.`); + return Promise.reject(ExitCode.FAILURE); + } return await validateDocument(document, services, logger); } +/** + * Extracts a document from a string that contains a model. + * Does not load an additional working directory. + */ export async function extractDocumentFromString( modelString: string, services: LangiumServices, From 96371465aa06a0d685e09898b5704cb40334051b Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Tue, 14 May 2024 10:26:34 +0200 Subject: [PATCH 02/13] Add test case files for invalid and valid publish-use relation of elements --- .../allowed-elements/invalid-unpublisheable.jv | 13 +++++++++++++ .../allowed-elements/valid-publisheable.jv | 12 ++++++++++++ .../invalid-aliased-use-published/published.jv | 5 +++++ .../invalid-aliased-use-published/using.jv | 9 +++++++++ .../main/using.jv | 9 +++++++++ .../published.jv | 5 +++++ .../invalid-use-unpublished/unpublished.jv | 5 +++++ .../named-use/invalid-use-unpublished/using.jv | 9 +++++++++ .../valid-aliased-use-published/published.jv | 5 +++++ .../named-use/valid-aliased-use-published/using.jv | 9 +++++++++ .../valid-use-aliased-published/published.jv | 7 +++++++ .../named-use/valid-use-aliased-published/using.jv | 9 +++++++++ .../valid-use-directly-published/published.jv | 5 +++++ .../named-use/valid-use-directly-published/using.jv | 9 +++++++++ .../valid-use-later-published/published.jv | 7 +++++++ .../named-use/valid-use-later-published/using.jv | 9 +++++++++ .../valid-use-multiple-published/published.jv | 6 ++++++ .../named-use/valid-use-multiple-published/using.jv | 9 +++++++++ .../nested/published.jv | 5 +++++ .../valid-use-published-deeper-dir/using.jv | 9 +++++++++ .../invalid-aliased-use-published/published.jv | 5 +++++ .../invalid-aliased-use-published/using.jv | 9 +++++++++ .../main/using.jv | 9 +++++++++ .../published.jv | 5 +++++ .../invalid-use-unpublished/unpublished.jv | 5 +++++ .../wildcard-use/invalid-use-unpublished/using.jv | 9 +++++++++ .../valid-aliased-use-published/published.jv | 5 +++++ .../valid-aliased-use-published/using.jv | 9 +++++++++ .../valid-use-aliased-published/published.jv | 7 +++++++ .../valid-use-aliased-published/using.jv | 9 +++++++++ .../valid-use-directly-published/published.jv | 5 +++++ .../valid-use-directly-published/using.jv | 9 +++++++++ .../valid-use-later-published/published.jv | 7 +++++++ .../wildcard-use/valid-use-later-published/using.jv | 9 +++++++++ .../valid-use-multiple-published/published.jv | 6 ++++++ .../valid-use-multiple-published/using.jv | 9 +++++++++ .../nested/published.jv | 5 +++++ .../valid-use-published-deeper-dir/using.jv | 9 +++++++++ 38 files changed, 287 insertions(+) create mode 100644 libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv create mode 100644 libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv create mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv diff --git a/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv b/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv new file mode 100644 index 000000000..27a95d6d7 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv @@ -0,0 +1,13 @@ + +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish pipeline PublishedPipeline {}; // pipelines cannot be published + +pipeline UnpublishedPipeline { // no publishing within pipelines allowed + publish block PublishedBlock oftype SomeBlockType {} + publish constraint PublishedConstraint on decimal: value >= 0; + publish valuetype PublishedValueType oftype decimal {}; + publish transform PublishedTransform {}; +}; \ No newline at end of file diff --git a/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv b/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv new file mode 100644 index 000000000..d7365cfeb --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish iotype PublishedIoType; +publish builtin constrainttype PublishedBuiltinConstraintType {}; +publish constraint PublishedConstraint on decimal: value >= 0; +publish valuetype PublishedValueType oftype decimal {}; +publish builtin blocktype PublishedBuiltinBlockType {}; +publish composite blocktype PublishedCompositeBlockType {}; +publish block PublishedBlock oftype PublishedCompositeBlockType {}; +publish transform PublishedTransform {}; \ No newline at end of file diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv new file mode 100644 index 000000000..b6108104c --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint as AliasedB } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ Aliased ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv new file mode 100644 index 000000000..1e58cf897 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint } from '../unpusblished.jv'; // traversing upwards beyond entrypoint is forbidden + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv new file mode 100644 index 000000000..d7752bcf9 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv new file mode 100644 index 000000000..93c2bb25f --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint UnpublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv new file mode 100644 index 000000000..de0634ec0 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { UnpublishedConstraint } from './unpusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ UnpublishedConstraint ]; // UnpublishedConstraint was not published +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv new file mode 100644 index 000000000..809b46c53 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint as Aliased } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ Aliased ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv new file mode 100644 index 000000000..f0197c2c7 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraintOtherName on decimal: value >= 0; + +publish PublishedConstraintOtherName as PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv new file mode 100644 index 000000000..1c5d6efb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv new file mode 100644 index 000000000..1c5d6efb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv new file mode 100644 index 000000000..48b665a6b --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraint on decimal: value >= 0; + +publish PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv new file mode 100644 index 000000000..1c5d6efb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv new file mode 100644 index 000000000..e25ead8cf --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint1 on decimal: value >= 0; +publish constraint PublishedConstraint2 on decimal: value >= 2; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv new file mode 100644 index 000000000..056bfeb5a --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint1, PublishedConstraint2 } from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint1, PublishedConstraint2 ]; +} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv new file mode 100644 index 000000000..9267d80a2 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use { PublishedConstraint } from './nested/pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv new file mode 100644 index 000000000..844949010 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * as AliasedB from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ Aliased.PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv new file mode 100644 index 000000000..67a099eed --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from '../unpusblished.jv'; // traversing upwards beyond entrypoint is forbidden + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv new file mode 100644 index 000000000..d7752bcf9 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv new file mode 100644 index 000000000..93c2bb25f --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint UnpublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv new file mode 100644 index 000000000..be9ab55fa --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './unpusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ UnpublishedConstraint ]; // UnpublishedConstraint was not published +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv new file mode 100644 index 000000000..cce4c2ae2 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * as Aliased from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ Aliased.PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv new file mode 100644 index 000000000..f0197c2c7 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraintOtherName on decimal: value >= 0; + +publish PublishedConstraintOtherName as PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv new file mode 100644 index 000000000..d6393ffb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv new file mode 100644 index 000000000..d6393ffb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv new file mode 100644 index 000000000..48b665a6b --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +constraint PublishedConstraint on decimal: value >= 0; + +publish PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv new file mode 100644 index 000000000..d6393ffb4 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv new file mode 100644 index 000000000..e25ead8cf --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint1 on decimal: value >= 0; +publish constraint PublishedConstraint2 on decimal: value >= 2; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv new file mode 100644 index 000000000..3a09d0e9c --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint1, PublishedConstraint2 ]; +} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv new file mode 100644 index 000000000..0a505abec --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv new file mode 100644 index 000000000..eac6f7ff9 --- /dev/null +++ b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './nested/pusblished.jv'; + +valuetype UsingValueType oftype decimal { + constraints: [ PublishedConstraint ]; +} From 473ba8a15e02596045b5a20f9eb6783ef45150f4 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 11:28:23 +0200 Subject: [PATCH 03/13] Change TableTransfromer blocktype to use prop "uses" instead of "use" to free the keyword "use" for imports --- example/electric-vehicles.jv | 4 ++-- .../tabular/exec/src/lib/table-transformer-executor.ts | 4 ++-- .../table-transformer-executor/valid-column-overwrite.jv | 2 +- .../table-transformer-executor/valid-column-type-change.jv | 2 +- .../valid-missing-input-column.jv | 2 +- .../assets/table-transformer-executor/valid-transfomer.jv | 2 +- .../valid-transform-type-missmatch.jv | 2 +- .../validation/checks/block-type-specific/property-body.ts | 2 +- .../src/stdlib/builtin-block-types/TableTransformer.jv | 6 +++--- .../invalid-input-columns-transform-port-missmatch.jv | 2 +- .../table-transformer/valid-correct-ports.jv | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/example/electric-vehicles.jv b/example/electric-vehicles.jv index 154d69d9a..8dbe7db0c 100644 --- a/example/electric-vehicles.jv +++ b/example/electric-vehicles.jv @@ -71,11 +71,11 @@ pipeline ElectricVehiclesPipeline { // 5. This block describes the application of a transform function // taking a column as input and adding another computed column. // The applied transform function is defined below and referenced - // by the "use" property. + // by the "uses" property. block ElectricRangeTransformer oftype TableTransformer { inputColumns: ["Electric Range"]; outputColumn: "Electric Range (km)"; - use: MilesToKilometers; + uses: MilesToKilometers; } // 6. Here, we define a transform function, taking parameters diff --git a/libs/extensions/tabular/exec/src/lib/table-transformer-executor.ts b/libs/extensions/tabular/exec/src/lib/table-transformer-executor.ts index 9d5240748..8d9301d59 100644 --- a/libs/extensions/tabular/exec/src/lib/table-transformer-executor.ts +++ b/libs/extensions/tabular/exec/src/lib/table-transformer-executor.ts @@ -47,7 +47,7 @@ export class TableTransformerExecutor extends AbstractBlockExecutor< context.valueTypeProvider.Primitives.Text, ); const usedTransform = context.getPropertyValue( - 'use', + 'uses', context.valueTypeProvider.Primitives.Transform, ); @@ -122,7 +122,7 @@ export class TableTransformerExecutor extends AbstractBlockExecutor< return R.err({ message: `Type ${inputColumn.valueType.getName()} of column "${inputColumnName}" is not convertible to type ${matchingInputDetails.valueType.getName()}`, diagnostic: { - node: context.getOrFailProperty('use'), + node: context.getOrFailProperty('uses'), }, }); } diff --git a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-overwrite.jv b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-overwrite.jv index 91c301ed4..aec0a2581 100644 --- a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-overwrite.jv +++ b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-overwrite.jv @@ -16,7 +16,7 @@ pipeline TestPipeline { block TestBlock oftype TableTransformer { inputColumns: ['index']; outputColumn: 'index'; - use: Double; + uses: Double; } block TestLoader oftype TestTableLoader { diff --git a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-type-change.jv b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-type-change.jv index a85a6b2ad..3c6bfffe7 100644 --- a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-type-change.jv +++ b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-column-type-change.jv @@ -16,7 +16,7 @@ pipeline TestPipeline { block TestBlock oftype TableTransformer { inputColumns: ['index']; outputColumn: 'index'; - use: ToBool; + uses: ToBool; } block TestLoader oftype TestTableLoader { diff --git a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-missing-input-column.jv b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-missing-input-column.jv index 44e535ffc..7d1a35c88 100644 --- a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-missing-input-column.jv +++ b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-missing-input-column.jv @@ -17,7 +17,7 @@ pipeline TestPipeline { block TestBlock oftype TableTransformer { inputColumns: ['index', 'id']; outputColumn: 'add'; - use: Add; + uses: Add; } block TestLoader oftype TestTableLoader { diff --git a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transfomer.jv b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transfomer.jv index 856d8024b..2a878c44a 100644 --- a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transfomer.jv +++ b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transfomer.jv @@ -16,7 +16,7 @@ pipeline TestPipeline { block TestBlock oftype TableTransformer { inputColumns: ['index']; outputColumn: 'index2'; - use: Double; + uses: Double; } block TestLoader oftype TestTableLoader { diff --git a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transform-type-missmatch.jv b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transform-type-missmatch.jv index 52675e73d..71ea4f0dc 100644 --- a/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transform-type-missmatch.jv +++ b/libs/extensions/tabular/exec/test/assets/table-transformer-executor/valid-transform-type-missmatch.jv @@ -16,7 +16,7 @@ pipeline TestPipeline { block TestBlock oftype TableTransformer { inputColumns: ['name']; outputColumn: 'index2'; - use: Double; + uses: Double; } block TestLoader oftype TestTableLoader { diff --git a/libs/language-server/src/lib/validation/checks/block-type-specific/property-body.ts b/libs/language-server/src/lib/validation/checks/block-type-specific/property-body.ts index fbc07f6cb..baadb77bd 100644 --- a/libs/language-server/src/lib/validation/checks/block-type-specific/property-body.ts +++ b/libs/language-server/src/lib/validation/checks/block-type-specific/property-body.ts @@ -123,7 +123,7 @@ function checkInputColumnsMatchTransformationPorts( propertyBody: PropertyBody, props: JayveeValidationProps, ): void { - const useProperty = propertyBody.properties.find((x) => x.name === 'use'); + const useProperty = propertyBody.properties.find((x) => x.name === 'uses'); const inputColumnsProperty = propertyBody.properties.find( (x) => x.name === 'inputColumns', ); diff --git a/libs/language-server/src/stdlib/builtin-block-types/TableTransformer.jv b/libs/language-server/src/stdlib/builtin-block-types/TableTransformer.jv index 6a022ffb9..6f45a933e 100644 --- a/libs/language-server/src/stdlib/builtin-block-types/TableTransformer.jv +++ b/libs/language-server/src/stdlib/builtin-block-types/TableTransformer.jv @@ -17,7 +17,7 @@ * block CelsiusToFahrenheitTransformer oftype TableTransformer { * inputColumns: ['temperature']; * outputColumn: 'temperature'; -* use: CelsiusToFahrenheit; +* uses: CelsiusToFahrenheit; * } * * @example Given a column "temperatureCelsius" with temperature values in Celsius, it adds a new column "temperatureFahrenheit" with computed values in Fahrenheit by using the `CelsiusToFahrenheit` transform. The transform itself is defined elsewhere in the model. @@ -32,7 +32,7 @@ * block CelsiusToFahrenheitTransformer oftype TableTransformer { * inputColumns: ['temperatureCelsius']; * outputColumn: 'temperatureFahrenheit'; -* use: CelsiusToFahrenheit; +* uses: CelsiusToFahrenheit; * } */ builtin blocktype TableTransformer { @@ -52,5 +52,5 @@ builtin blocktype TableTransformer { /** * Reference to the transform that is applied to the column. */ - property use oftype Transform; + property uses oftype Transform; } \ No newline at end of file diff --git a/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/invalid-input-columns-transform-port-missmatch.jv b/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/invalid-input-columns-transform-port-missmatch.jv index 4179d0a04..983735e7e 100644 --- a/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/invalid-input-columns-transform-port-missmatch.jv +++ b/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/invalid-input-columns-transform-port-missmatch.jv @@ -13,7 +13,7 @@ pipeline Pipeline { block Test oftype TableTransformer { inputColumns: ['input1', 'input2']; outputColumn: 'output'; - use: TestTransform; + uses: TestTransform; } block TestExtractor oftype TestTableExtractor { diff --git a/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/valid-correct-ports.jv b/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/valid-correct-ports.jv index c6da883da..24b5db189 100644 --- a/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/valid-correct-ports.jv +++ b/libs/language-server/src/test/assets/property-body/block-type-specific/table-transformer/valid-correct-ports.jv @@ -13,7 +13,7 @@ pipeline Pipeline { block Test oftype TableTransformer { inputColumns: ['input1']; outputColumn: 'output'; - use: TestTransform; + uses: TestTransform; } block TestExtractor oftype TestTableExtractor { From 6eb5d2b3a7840bdf586eaa4471d4c861787a36de Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 11:28:56 +0200 Subject: [PATCH 04/13] Add "use" keyword in import definition and validation that used files exist --- libs/language-server/src/grammar/main.langium | 5 +- libs/language-server/src/lib/jayvee-module.ts | 4 + .../src/lib/services/import-resolver.ts | 41 +++++ .../checks/import-definition.spec.ts | 163 ++++++++++++++++++ .../validation/checks/import-definition.ts | 30 ++++ .../src/lib/validation/validation-registry.ts | 9 + .../deeper/existing-imported-file-deeper.jv | 3 + .../valid-imported-file-exists-higher-dir.jv | 5 + .../existing-imported-file.jv | 3 + .../existing-imported-file.njv | 3 + ...id-imported-file-with-wrong-file-ending.jv | 6 + .../invalid-imported-not-existing-file.jv | 6 + .../valid-imported-file-exists-deeper-dir.jv | 6 + .../valid-imported-file-exists-same-dir.jv | 6 + libs/language-server/src/test/utils.ts | 2 + 15 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 libs/language-server/src/lib/services/import-resolver.ts create mode 100644 libs/language-server/src/lib/validation/checks/import-definition.spec.ts create mode 100644 libs/language-server/src/lib/validation/checks/import-definition.ts create mode 100644 libs/language-server/src/test/assets/import-definition/deeper/existing-imported-file-deeper.jv create mode 100644 libs/language-server/src/test/assets/import-definition/deeper/valid-imported-file-exists-higher-dir.jv create mode 100644 libs/language-server/src/test/assets/import-definition/existing-imported-file.jv create mode 100644 libs/language-server/src/test/assets/import-definition/existing-imported-file.njv create mode 100644 libs/language-server/src/test/assets/import-definition/invalid-imported-file-with-wrong-file-ending.jv create mode 100644 libs/language-server/src/test/assets/import-definition/invalid-imported-not-existing-file.jv create mode 100644 libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-deeper-dir.jv create mode 100644 libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-same-dir.jv diff --git a/libs/language-server/src/grammar/main.langium b/libs/language-server/src/grammar/main.langium index 6e05e1296..eb58f07ff 100644 --- a/libs/language-server/src/grammar/main.langium +++ b/libs/language-server/src/grammar/main.langium @@ -15,7 +15,8 @@ import './io-type' entry JayveeModel: ( - pipelines+=PipelineDefinition + imports+=ImportDefinition + | pipelines+=PipelineDefinition | valueTypes+=(CustomValuetypeDefinition | BuiltinValuetypeDefinition) | constraints+=ConstraintDefinition | transforms+=TransformDefinition @@ -25,3 +26,5 @@ entry JayveeModel: )*; +ImportDefinition: + 'use' '*' 'from' path=STRING ';'; diff --git a/libs/language-server/src/lib/jayvee-module.ts b/libs/language-server/src/lib/jayvee-module.ts index a9150dffe..39c182e7c 100644 --- a/libs/language-server/src/lib/jayvee-module.ts +++ b/libs/language-server/src/lib/jayvee-module.ts @@ -28,6 +28,7 @@ import { JayveeWorkspaceManager } from './builtin-library/jayvee-workspace-manag import { JayveeCompletionProvider } from './completion/jayvee-completion-provider'; import { JayveeHoverProvider } from './hover/jayvee-hover-provider'; import { JayveeValueConverter } from './jayvee-value-converter'; +import { JayveeImportResolver } from './services/import-resolver'; import { RuntimeParameterProvider } from './services/runtime-parameter-provider'; import { JayveeValidationRegistry } from './validation/validation-registry'; @@ -46,6 +47,7 @@ export interface JayveeAddedServices { validation: { ValidationRegistry: JayveeValidationRegistry; }; + ImportResolver: JayveeImportResolver; } /** @@ -92,6 +94,8 @@ export const JayveeModule: Module< services.operators.EvaluatorRegistry, services.ValueTypeProvider, ), + ImportResolver: (services) => + new JayveeImportResolver(services.shared.workspace.LangiumDocuments), }; export const JayveeSharedModule: Module< diff --git a/libs/language-server/src/lib/services/import-resolver.ts b/libs/language-server/src/lib/services/import-resolver.ts new file mode 100644 index 000000000..cb9b4f971 --- /dev/null +++ b/libs/language-server/src/lib/services/import-resolver.ts @@ -0,0 +1,41 @@ +import { AstUtils, type LangiumDocuments, type URI, UriUtils } from 'langium'; + +import { type ImportDefinition, type JayveeModel, isJayveeModel } from '../ast'; + +export class JayveeImportResolver { + constructor(protected documents: LangiumDocuments) {} + + resolveImport(importDefinition: ImportDefinition): JayveeModel | undefined { + const resolvedUri = this.resolveImportUri(importDefinition); + if (!resolvedUri) { + return undefined; + } + + const resolvedDocument = this.documents.getDocument(resolvedUri); + if (!resolvedDocument) { + return undefined; + } + + const parsedModel = resolvedDocument.parseResult.value; + if (!isJayveeModel(parsedModel)) { + return undefined; + } + + return parsedModel; + } + + resolveImportUri(importDefinition: ImportDefinition): URI | undefined { + if ( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + importDefinition.path === undefined || + importDefinition.path.length === 0 + ) { + return undefined; + } + + const dirUri = UriUtils.dirname(AstUtils.getDocument(importDefinition).uri); + const modelPath = importDefinition.path; + + return UriUtils.resolvePath(dirUri, modelPath); + } +} diff --git a/libs/language-server/src/lib/validation/checks/import-definition.spec.ts b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts new file mode 100644 index 000000000..6419fea51 --- /dev/null +++ b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts @@ -0,0 +1,163 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import path from 'node:path'; + +import { type AstNode, type LangiumDocument, URI } from 'langium'; +import { NodeFileSystem } from 'langium/node'; +import { vi } from 'vitest'; + +import { + type JayveeServices, + createJayveeServices, + initializeWorkspace, + isJayveeModel, +} from '../../../lib'; +import { + type ParseHelperOptions, + createJayveeValidationProps, + expectNoParserAndLexerErrors, + validationAcceptorMockImpl, +} from '../../../test'; + +import { validateImportDefinition } from './import-definition'; + +describe('Validation of ImportDefinition', () => { + let services: JayveeServices; + const validationAcceptorMock = vi.fn(validationAcceptorMockImpl); + + async function parse( + relativeTestFilePath: string, + options?: ParseHelperOptions, + ): Promise> { + const testFilePath = path.resolve( + __dirname, + '../../../test/assets/', + relativeTestFilePath, + ); + const testFileUri = URI.parse(testFilePath); + const documentBuilder = services.shared.workspace.DocumentBuilder; + await initializeWorkspace(services, [ + { + name: 'projectDir', + uri: workingDir, + }, + ]); + const testDocument = + services.shared.workspace.LangiumDocuments.getDocument(testFileUri); + + assert( + testDocument !== undefined, + 'Could not load test document. Error in test setup!', + ); + + await documentBuilder.build([testDocument], options); + return testDocument; + } + + const workingDir = path.resolve(__dirname, '../../../test/assets/'); + + async function parseAndValidateImportDefinition( + relativeTestFilePath: string, + ) { + const document = await parse(relativeTestFilePath); + expectNoParserAndLexerErrors(document); + + const parsedModel = document.parseResult.value; + assert(isJayveeModel(parsedModel), 'Test file is not valid Jayvee model'); + assert( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + parsedModel.imports !== undefined && parsedModel.imports.length > 0, + 'Test file does not contain imports', + ); + + for (const importDefinition of parsedModel.imports) { + validateImportDefinition( + importDefinition, + createJayveeValidationProps(validationAcceptorMock, services), + ); + } + } + + beforeEach(() => { + // Create language services + services = createJayveeServices(NodeFileSystem).Jayvee; + }); + + afterEach(() => { + // Reset mock + validationAcceptorMock.mockReset(); + }); + + describe('ImportDefinition syntax', () => { + it('should have no error if file exists in same directory', async () => { + const relativeTestFilePath = + 'import-definition/valid-imported-file-exists-same-dir.jv'; + + await parseAndValidateImportDefinition(relativeTestFilePath); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(0); + }); + + it('should have no error if file exists in deeper directory', async () => { + const relativeTestFilePath = + 'import-definition/valid-imported-file-exists-deeper-dir.jv'; + + await parseAndValidateImportDefinition(relativeTestFilePath); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(0); + }); + + it('should have no error if file exists in deeper directory', async () => { + const relativeTestFilePath = + 'import-definition/deeper/valid-imported-file-exists-higher-dir.jv'; + + await parseAndValidateImportDefinition(relativeTestFilePath); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(0); + }); + + it('should diagnose error on imported file that does not exist', async () => { + const relativeTestFilePath = + 'import-definition/invalid-imported-not-existing-file.jv'; + + await parseAndValidateImportDefinition(relativeTestFilePath); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(2); + expect(validationAcceptorMock).toHaveBeenNthCalledWith( + 1, + 'error', + 'Import cannot be resolved.', + expect.any(Object), + ); + expect(validationAcceptorMock).toHaveBeenNthCalledWith( + 2, + 'error', + 'Import cannot be resolved.', + expect.any(Object), + ); + }); + + it('should diagnose error on unsupported file ending', async () => { + const relativeTestFilePath = + 'import-definition/invalid-imported-file-with-wrong-file-ending.jv'; + + await parseAndValidateImportDefinition(relativeTestFilePath); + + expect(validationAcceptorMock).toHaveBeenCalledTimes(2); + expect(validationAcceptorMock).toHaveBeenNthCalledWith( + 1, + 'error', + 'Import cannot be resolved.', + expect.any(Object), + ); + expect(validationAcceptorMock).toHaveBeenNthCalledWith( + 2, + 'error', + 'Import cannot be resolved.', + expect.any(Object), + ); + }); + }); +}); diff --git a/libs/language-server/src/lib/validation/checks/import-definition.ts b/libs/language-server/src/lib/validation/checks/import-definition.ts new file mode 100644 index 000000000..6c4cedb64 --- /dev/null +++ b/libs/language-server/src/lib/validation/checks/import-definition.ts @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { type ImportDefinition } from '../../ast/generated/ast'; +import { type JayveeValidationProps } from '../validation-registry'; + +/** + * See https://jvalue.github.io/jayvee/docs/dev/guides/working-with-the-ast/ for why the following ESLint rule is disabled for this file. + */ + +export function validateImportDefinition( + importDefinition: ImportDefinition, + props: JayveeValidationProps, +): void { + checkPathExists(importDefinition, props); +} + +function checkPathExists( + importDefinition: ImportDefinition, + props: JayveeValidationProps, +): void { + const resolvedImport = props.importResolver.resolveImport(importDefinition); + if (resolvedImport === undefined) { + props.validationContext.accept('error', 'Import cannot be resolved.', { + node: importDefinition, + property: 'path', + }); + } +} diff --git a/libs/language-server/src/lib/validation/validation-registry.ts b/libs/language-server/src/lib/validation/validation-registry.ts index 50656bf08..fb7a7d600 100644 --- a/libs/language-server/src/lib/validation/validation-registry.ts +++ b/libs/language-server/src/lib/validation/validation-registry.ts @@ -20,12 +20,14 @@ import { import { type JayveeAstType } from '../ast/generated/ast'; import type { JayveeServices } from '../jayvee-module'; import { type RuntimeParameterProvider } from '../services'; +import { type JayveeImportResolver } from '../services/import-resolver'; import { validateBlockDefinition } from './checks/block-definition'; import { validateBlockTypeDefinition } from './checks/block-type-definition'; import { validateColumnId } from './checks/column-id'; import { validateCompositeBlockTypeDefinition } from './checks/composite-block-type-definition'; import { validateExpressionConstraintDefinition } from './checks/expression-constraint-definition'; +import { validateImportDefinition } from './checks/import-definition'; import { validateJayveeModel } from './checks/jayvee-model'; import { validatePipeDefinition } from './checks/pipe-definition'; import { validatePipelineDefinition } from './checks/pipeline-definition'; @@ -47,6 +49,7 @@ export class JayveeValidationRegistry extends ValidationRegistry { private readonly operatorEvaluatorRegistry: OperatorEvaluatorRegistry; private readonly wrapperFactories: WrapperFactoryProvider; private readonly valueTypeProvider: ValueTypeProvider; + private readonly importResolver: JayveeImportResolver; constructor(services: JayveeServices) { super(services); @@ -56,8 +59,10 @@ export class JayveeValidationRegistry extends ValidationRegistry { this.operatorEvaluatorRegistry = services.operators.EvaluatorRegistry; this.wrapperFactories = services.WrapperFactories; this.valueTypeProvider = services.ValueTypeProvider; + this.importResolver = services.ImportResolver; this.registerJayveeValidationChecks({ + ImportDefinition: validateImportDefinition, BuiltinBlockTypeDefinition: validateBlockTypeDefinition, BlockDefinition: validateBlockDefinition, CompositeBlockTypeDefinition: validateCompositeBlockTypeDefinition, @@ -85,6 +90,7 @@ export class JayveeValidationRegistry extends ValidationRegistry { this.operatorEvaluatorRegistry, this.wrapperFactories, this.valueTypeProvider, + this.importResolver, ); this.addEntry(type, { @@ -101,6 +107,7 @@ export class JayveeValidationRegistry extends ValidationRegistry { operatorEvaluatorRegistry: OperatorEvaluatorRegistry, wrapperFactories: WrapperFactoryProvider, valueTypeProvider: ValueTypeProvider, + importResolver: JayveeImportResolver, ): ValidationCheck { return (node: T, accept: ValidationAcceptor): MaybePromise => { const validationContext = new ValidationContext( @@ -117,6 +124,7 @@ export class JayveeValidationRegistry extends ValidationRegistry { evaluationContext: evaluationContext, wrapperFactories: wrapperFactories, valueTypeProvider: valueTypeProvider, + importResolver: importResolver, }); }; } @@ -133,6 +141,7 @@ export interface JayveeValidationProps { evaluationContext: EvaluationContext; wrapperFactories: WrapperFactoryProvider; valueTypeProvider: ValueTypeProvider; + importResolver: JayveeImportResolver; } export type JayveeValidationCheck = ( node: T, diff --git a/libs/language-server/src/test/assets/import-definition/deeper/existing-imported-file-deeper.jv b/libs/language-server/src/test/assets/import-definition/deeper/existing-imported-file-deeper.jv new file mode 100644 index 000000000..aa64689f8 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/deeper/existing-imported-file-deeper.jv @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only diff --git a/libs/language-server/src/test/assets/import-definition/deeper/valid-imported-file-exists-higher-dir.jv b/libs/language-server/src/test/assets/import-definition/deeper/valid-imported-file-exists-higher-dir.jv new file mode 100644 index 000000000..40881f261 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/deeper/valid-imported-file-exists-higher-dir.jv @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from '../existing-imported-file.jv'; diff --git a/libs/language-server/src/test/assets/import-definition/existing-imported-file.jv b/libs/language-server/src/test/assets/import-definition/existing-imported-file.jv new file mode 100644 index 000000000..aa64689f8 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/existing-imported-file.jv @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only diff --git a/libs/language-server/src/test/assets/import-definition/existing-imported-file.njv b/libs/language-server/src/test/assets/import-definition/existing-imported-file.njv new file mode 100644 index 000000000..aa64689f8 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/existing-imported-file.njv @@ -0,0 +1,3 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only diff --git a/libs/language-server/src/test/assets/import-definition/invalid-imported-file-with-wrong-file-ending.jv b/libs/language-server/src/test/assets/import-definition/invalid-imported-file-with-wrong-file-ending.jv new file mode 100644 index 000000000..0723eec23 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/invalid-imported-file-with-wrong-file-ending.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from 'existing-imported-file.njv'; +use * from './existing-imported-file.njv'; diff --git a/libs/language-server/src/test/assets/import-definition/invalid-imported-not-existing-file.jv b/libs/language-server/src/test/assets/import-definition/invalid-imported-not-existing-file.jv new file mode 100644 index 000000000..063d2b3e0 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/invalid-imported-not-existing-file.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from 'not-existing-imported-file-deeper.jv'; +use * from './not-existing-imported-file-deeper.jv'; diff --git a/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-deeper-dir.jv b/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-deeper-dir.jv new file mode 100644 index 000000000..5e8a4eb3e --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-deeper-dir.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from 'deeper/existing-imported-file-deeper.jv'; +use * from './deeper/existing-imported-file-deeper.jv'; diff --git a/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-same-dir.jv b/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-same-dir.jv new file mode 100644 index 000000000..d24ee6178 --- /dev/null +++ b/libs/language-server/src/test/assets/import-definition/valid-imported-file-exists-same-dir.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from 'existing-imported-file.jv'; +use * from './existing-imported-file.jv'; diff --git a/libs/language-server/src/test/utils.ts b/libs/language-server/src/test/utils.ts index faa868c17..6f964da63 100644 --- a/libs/language-server/src/test/utils.ts +++ b/libs/language-server/src/test/utils.ts @@ -77,6 +77,7 @@ export function createJayveeValidationProps( const wrapperFactories = services.WrapperFactories; const operatorTypeComputerRegistry = services.operators.TypeComputerRegistry; const runtimeParameterProvider = services.RuntimeParameterProvider; + const importResolver = services.ImportResolver; return { validationContext: new ValidationContext( @@ -90,5 +91,6 @@ export function createJayveeValidationProps( ), valueTypeProvider: valueTypeProvider, wrapperFactories: wrapperFactories, + importResolver: importResolver, }; } From be786417da654d308e807ed5cbc5c1fd81b7dc42 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 14:00:29 +0200 Subject: [PATCH 05/13] Adapt scoping to export root-level elements and make them importable --- .../runtime-parameter-literal.spec.ts | 12 ++- libs/language-server/src/lib/jayvee-module.ts | 6 ++ .../src/lib/lsp/jayvee-scope-computation.ts | 52 ++++++++++ .../src/lib/lsp/jayvee-scope-provider.ts | 99 +++++++++++++++++++ .../src/lib/services/import-resolver.ts | 6 +- .../language-server/src/lib/services/index.ts | 1 + 6 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 libs/language-server/src/lib/lsp/jayvee-scope-computation.ts create mode 100644 libs/language-server/src/lib/lsp/jayvee-scope-provider.ts diff --git a/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts b/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts index e9b922b90..b0232e504 100644 --- a/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts +++ b/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts @@ -9,6 +9,7 @@ import { DefaultOperatorEvaluatorRegistry, DefaultOperatorTypeComputerRegistry, EvaluationContext, + JayveeImportResolver, type JayveeServices, type RuntimeParameterLiteral, RuntimeParameterProvider, @@ -83,6 +84,10 @@ describe('Validation of validateRuntimeParameterLiteral', () => { wrapperFactories, ); + const importResolver = new JayveeImportResolver( + services.shared.workspace.LangiumDocuments, + ); + validateRuntimeParameterLiteral(runtimeParameter, { validationContext: new ValidationContext( validationAcceptorMock, @@ -95,6 +100,7 @@ describe('Validation of validateRuntimeParameterLiteral', () => { ), valueTypeProvider: valueTypeProvider, wrapperFactories: wrapperFactories, + importResolver: importResolver, }); } @@ -105,7 +111,7 @@ describe('Validation of validateRuntimeParameterLiteral', () => { await loadTestExtensions(services, [ path.resolve( __dirname, - '../../test/assets/runtime-parameter-literal/test-extension/TestBlockTypes.jv', + '../../test/assets/runtime-parameter-literal/test-extension', ), ]); locator = services.workspace.AstNodeLocator; @@ -139,7 +145,7 @@ describe('Validation of validateRuntimeParameterLiteral', () => { await parseAndValidateRuntimeParameterLiteral( text, - new Map([['INTEGER_ENV', 'Value 1']]), + new Map([['INTEGER_ENV', 'Value 1']]), // wrong parameter type ); expect(validationAcceptorMock).toHaveBeenCalledTimes(1); @@ -155,7 +161,7 @@ describe('Validation of validateRuntimeParameterLiteral', () => { 'runtime-parameter-literal/valid-text-runtime-property.jv', ); - await parseAndValidateRuntimeParameterLiteral(text); + await parseAndValidateRuntimeParameterLiteral(text); // don't pass parameter expect(validationAcceptorMock).toHaveBeenCalledTimes(1); expect(validationAcceptorMock).toHaveBeenCalledWith( diff --git a/libs/language-server/src/lib/jayvee-module.ts b/libs/language-server/src/lib/jayvee-module.ts index 39c182e7c..58563ae51 100644 --- a/libs/language-server/src/lib/jayvee-module.ts +++ b/libs/language-server/src/lib/jayvee-module.ts @@ -28,6 +28,8 @@ import { JayveeWorkspaceManager } from './builtin-library/jayvee-workspace-manag import { JayveeCompletionProvider } from './completion/jayvee-completion-provider'; import { JayveeHoverProvider } from './hover/jayvee-hover-provider'; import { JayveeValueConverter } from './jayvee-value-converter'; +import { JayveeScopeComputation } from './lsp/jayvee-scope-computation'; +import { JayveeScopeProvider } from './lsp/jayvee-scope-provider'; import { JayveeImportResolver } from './services/import-resolver'; import { RuntimeParameterProvider } from './services/runtime-parameter-provider'; import { JayveeValidationRegistry } from './validation/validation-registry'; @@ -79,6 +81,10 @@ export const JayveeModule: Module< HoverProvider: (services: JayveeServices) => new JayveeHoverProvider(services), }, + references: { + ScopeProvider: (services) => new JayveeScopeProvider(services), + ScopeComputation: (service) => new JayveeScopeComputation(service), + }, RuntimeParameterProvider: () => new RuntimeParameterProvider(), operators: { TypeComputerRegistry: (services) => diff --git a/libs/language-server/src/lib/lsp/jayvee-scope-computation.ts b/libs/language-server/src/lib/lsp/jayvee-scope-computation.ts new file mode 100644 index 000000000..0acce4f77 --- /dev/null +++ b/libs/language-server/src/lib/lsp/jayvee-scope-computation.ts @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { + type AstNode, + type AstNodeDescription, + DefaultScopeComputation, + type LangiumCoreServices, + type LangiumDocument, +} from 'langium'; + +import { + isBuiltinConstrainttypeDefinition, + isConstraintDefinition, + isIotypeDefinition, + isReferenceableBlockTypeDefinition, + isTransformDefinition, + isValuetypeDefinition, +} from '../ast'; + +export class JayveeScopeComputation extends DefaultScopeComputation { + constructor(services: LangiumCoreServices) { + super(services); + } + + protected override exportNode( + node: AstNode, + exports: AstNodeDescription[], + document: LangiumDocument, + ): void { + // export the exportable top-level elements + if (!this.isExportable(node)) { + return; + } + + super.exportNode(node, exports, document); + } + + isExportable(node: AstNode) { + // pipelines are not exported + + return ( + isValuetypeDefinition(node) || + isConstraintDefinition(node) || + isTransformDefinition(node) || + isReferenceableBlockTypeDefinition(node) || + isBuiltinConstrainttypeDefinition(node) || + isIotypeDefinition(node) + ); + } +} diff --git a/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts b/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts new file mode 100644 index 000000000..845d13a5f --- /dev/null +++ b/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import { + AstUtils, + DefaultScopeProvider, + EMPTY_SCOPE, + type LangiumDocuments, + MapScope, + type ReferenceInfo, + type Scope, + URI, +} from 'langium'; + +import { type JayveeModel, isJayveeModel } from '../ast'; +import { getStdLib } from '../builtin-library'; +import { type JayveeServices } from '../jayvee-module'; +import { type JayveeImportResolver } from '../services/import-resolver'; + +export class JayveeScopeProvider extends DefaultScopeProvider { + protected readonly langiumDocuments: LangiumDocuments; + protected readonly importResover: JayveeImportResolver; + + constructor(services: JayveeServices) { + super(services); + this.langiumDocuments = services.shared.workspace.LangiumDocuments; + this.importResover = services.ImportResolver; + } + + protected override getGlobalScope( + referenceType: string, + context: ReferenceInfo, + ): Scope { + const jayveeModel = AstUtils.getContainerOfType( + context.container, + isJayveeModel, + ); + if (!jayveeModel) { + return EMPTY_SCOPE; + } + + const importedUris = new Set(); + this.gatherImports(jayveeModel, importedUris); + this.gatherBuiltins(importedUris); + + const importedElements = this.indexManager.allElements( + referenceType, + importedUris, + ); + + return new MapScope(importedElements); + } + + /** + * Add all builtins URIs to @param importedUris + */ + private gatherBuiltins(importedUris: Set) { + const builtins = getStdLib(); + const uris = Object.keys(builtins); + + for (const uri of uris) { + // without formatting, the document might not be found + const formattedUri = URI.parse(uri).toString(); + importedUris.add(formattedUri); + } + } + + /** + * Recursively add all imported URIs to @param importedUris + */ + private gatherImports( + jayveeModel: JayveeModel, + importedUris: Set, + ): void { + for (const importDefinition of jayveeModel.imports) { + const uri = this.importResover.resolveImportUri(importDefinition); + if (uri === undefined) { + break; + } + + if (importedUris.has(uri.toString())) { + break; // end recursion + } + + importedUris.add(uri.toString()); + const importedDocument = this.langiumDocuments.getDocument(uri); + if (importedDocument === undefined) { + break; + } + + const rootNode = importedDocument.parseResult.value; + if (!isJayveeModel(rootNode)) { + break; + } + this.gatherImports(rootNode, importedUris); + } + } +} diff --git a/libs/language-server/src/lib/services/import-resolver.ts b/libs/language-server/src/lib/services/import-resolver.ts index cb9b4f971..7689a17d7 100644 --- a/libs/language-server/src/lib/services/import-resolver.ts +++ b/libs/language-server/src/lib/services/import-resolver.ts @@ -1,6 +1,10 @@ import { AstUtils, type LangiumDocuments, type URI, UriUtils } from 'langium'; -import { type ImportDefinition, type JayveeModel, isJayveeModel } from '../ast'; +import { + type ImportDefinition, + type JayveeModel, + isJayveeModel, +} from '../ast/generated/ast'; export class JayveeImportResolver { constructor(protected documents: LangiumDocuments) {} diff --git a/libs/language-server/src/lib/services/index.ts b/libs/language-server/src/lib/services/index.ts index d49eebc13..49c22d868 100644 --- a/libs/language-server/src/lib/services/index.ts +++ b/libs/language-server/src/lib/services/index.ts @@ -3,3 +3,4 @@ // SPDX-License-Identifier: AGPL-3.0-only export * from './runtime-parameter-provider'; +export * from './import-resolver'; From 5d168d5edd27ff526703422dff1bfdbb6157c66c Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 14:39:31 +0200 Subject: [PATCH 06/13] Add new test helper parseTestFileInWorkingDir --- libs/interpreter-lib/src/parsing-util.spec.ts | 65 ++++++++----------- .../runtime-parameter-literal.spec.ts | 64 ++++++------------ .../invalid-extension.lv | 2 + .../extractDocumentFromFile/valid-model.jv | 2 + .../invalid-model.jv | 2 + .../extractDocumentFromString/valid-model.jv | 2 + .../invalid-wrong-loader-type.jv | 2 + .../validateDocument/valid-document.jv | 2 + .../valid-simplify-warning.jv | 2 + .../valid-integer-runtime-property.jv | 2 + .../valid-text-runtime-property.jv | 2 + .../checks/import-definition.spec.ts | 42 ++---------- libs/language-server/src/test/utils.ts | 36 +++++++++- 13 files changed, 106 insertions(+), 119 deletions(-) diff --git a/libs/interpreter-lib/src/parsing-util.spec.ts b/libs/interpreter-lib/src/parsing-util.spec.ts index a253399e4..349f8ed1f 100644 --- a/libs/interpreter-lib/src/parsing-util.spec.ts +++ b/libs/interpreter-lib/src/parsing-util.spec.ts @@ -8,47 +8,25 @@ import { CachedLogger, DiagnosticSeverity } from '@jvalue/jayvee-execution'; import { type JayveeServices, createJayveeServices, + initializeWorkspace, } from '@jvalue/jayvee-language-server'; import { - type ParseHelperOptions, expectNoParserAndLexerErrors, - loadTestExtensions, - parseHelper, - readJvTestAssetHelper, + parseTestFileInWorkingDir, } from '@jvalue/jayvee-language-server/test'; -import { type AstNode, type LangiumDocument } from 'langium'; import { NodeFileSystem } from 'langium/node'; import { extractDocumentFromFile, validateDocument } from './parsing-util'; describe('Validation of parsing-util', () => { - let parse: ( - input: string, - options?: ParseHelperOptions, - ) => Promise>; - + const WORKING_DIR = path.resolve(__dirname, '../test/assets/parsing-util/'); let services: JayveeServices; const logger = new CachedLogger(true, undefined, false); - const readJvTestAsset = readJvTestAssetHelper( - __dirname, - '../test/assets/parsing-util/', - ); - - beforeAll(async () => { + beforeAll(() => { // Create language services services = createJayveeServices(NodeFileSystem).Jayvee; - - await loadTestExtensions(services, [ - path.resolve( - __dirname, - '../test/assets/parsing-util/test-extension/TestBlockTypes.jv', - ), - ]); - - // Parse function for Jayvee (without validation) - parse = parseHelper(services); }); afterEach(() => { @@ -56,17 +34,21 @@ describe('Validation of parsing-util', () => { }); describe('Function of validateDocument', () => { - async function parseAndValidateDocument(input: string) { - const document = await parse(input); + async function parseAndValidateDocument(relativeTestFilePath: string) { + const document = await parseTestFileInWorkingDir( + WORKING_DIR, + relativeTestFilePath, + services, + ); expectNoParserAndLexerErrors(document); return validateDocument(document, services, logger); } it('should diagnose no error on valid document', async () => { - const text = readJvTestAsset('validateDocument/valid-document.jv'); + const relativeTestFilePath = 'validateDocument/valid-document.jv'; - await parseAndValidateDocument(text); + await parseAndValidateDocument(relativeTestFilePath); expect(logger.getLogs(DiagnosticSeverity.ERROR)).toHaveLength(0); expect(logger.getLogs(DiagnosticSeverity.INFO)).toHaveLength(0); @@ -76,12 +58,11 @@ describe('Validation of parsing-util', () => { }); it('should diagnose error on wrong loader type', async () => { - const text = readJvTestAsset( - 'validateDocument/invalid-wrong-loader-type.jv', - ); + const relativeTestFilePath = + 'validateDocument/invalid-wrong-loader-type.jv'; try { - await parseAndValidateDocument(text); + await parseAndValidateDocument(relativeTestFilePath); } catch (e) { expect(logger.getLogs(DiagnosticSeverity.INFO)).toHaveLength(0); expect(logger.getLogs(DiagnosticSeverity.ERROR)).toHaveLength(2 * 5); // 2 calls that get formated to 5 lines each @@ -92,12 +73,10 @@ describe('Validation of parsing-util', () => { }); it('should diagnose no error on nonErr diagnostics', async () => { - const text = readJvTestAsset( - 'validateDocument/valid-simplify-warning.jv', - ); + const relativeTestFilePath = 'validateDocument/valid-simplify-warning.jv'; try { - await parseAndValidateDocument(text); + await parseAndValidateDocument(relativeTestFilePath); } catch (e) { expect(logger.getLogs(DiagnosticSeverity.INFO)).toHaveLength(0); expect(logger.getLogs(DiagnosticSeverity.ERROR)).toHaveLength(1); @@ -109,6 +88,16 @@ describe('Validation of parsing-util', () => { }); describe('Function of extractDocumentFromFile', () => { + beforeAll(async () => { + // register test extension dir as not below test files + await initializeWorkspace(services, [ + { + name: 'testExtension', + uri: WORKING_DIR, + }, + ]); + }); + it('should diagnose no error on valid model file', async () => { await extractDocumentFromFile( path.resolve( diff --git a/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts b/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts index b0232e504..befeea882 100644 --- a/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts +++ b/libs/interpreter-lib/src/validation-checks/runtime-parameter-literal.spec.ts @@ -19,44 +19,33 @@ import { createJayveeServices, } from '@jvalue/jayvee-language-server'; import { - type ParseHelperOptions, expectNoParserAndLexerErrors, - loadTestExtensions, - parseHelper, - readJvTestAssetHelper, + parseTestFileInWorkingDir, validationAcceptorMockImpl, } from '@jvalue/jayvee-language-server/test'; -import { - type AstNode, - type AstNodeLocator, - type LangiumDocument, -} from 'langium'; +import { type AstNodeLocator } from 'langium'; import { NodeFileSystem } from 'langium/node'; import { vi } from 'vitest'; import { validateRuntimeParameterLiteral } from './runtime-parameter-literal'; describe('Validation of validateRuntimeParameterLiteral', () => { - let parse: ( - input: string, - options?: ParseHelperOptions, - ) => Promise>; + const WORKING_DIR = path.resolve(__dirname, '../../test/assets/'); - let locator: AstNodeLocator; let services: JayveeServices; + let locator: AstNodeLocator; const validationAcceptorMock = vi.fn(validationAcceptorMockImpl); - const readJvTestAsset = readJvTestAssetHelper( - __dirname, - '../../test/assets/', - ); - async function parseAndValidateRuntimeParameterLiteral( - input: string, + relativeTestFilePath: string, runtimeParameters?: Map, ) { - const document = await parse(input); + const document = await parseTestFileInWorkingDir( + WORKING_DIR, + relativeTestFilePath, + services, + ); expectNoParserAndLexerErrors(document); const runtimeParameter = locator.getAstNode( @@ -104,20 +93,10 @@ describe('Validation of validateRuntimeParameterLiteral', () => { }); } - beforeAll(async () => { + beforeAll(() => { // Create language services services = createJayveeServices(NodeFileSystem).Jayvee; - - await loadTestExtensions(services, [ - path.resolve( - __dirname, - '../../test/assets/runtime-parameter-literal/test-extension', - ), - ]); locator = services.workspace.AstNodeLocator; - - // Parse function for Jayvee (without validation) - parse = parseHelper(services); }); afterEach(() => { @@ -126,12 +105,11 @@ describe('Validation of validateRuntimeParameterLiteral', () => { }); it('should diagnose no error on valid runtime parameter value', async () => { - const text = readJvTestAsset( - 'runtime-parameter-literal/valid-text-runtime-property.jv', - ); + const relativeTestFilePath = + 'runtime-parameter-literal/valid-text-runtime-property.jv'; await parseAndValidateRuntimeParameterLiteral( - text, + relativeTestFilePath, new Map([['TEXT_ENV', 'Value 1']]), ); @@ -139,12 +117,11 @@ describe('Validation of validateRuntimeParameterLiteral', () => { }); it('should diagnose error on failed runtime parameter value parsing', async () => { - const text = readJvTestAsset( - 'runtime-parameter-literal/valid-integer-runtime-property.jv', - ); + const relativeTestFilePath = + 'runtime-parameter-literal/valid-integer-runtime-property.jv'; await parseAndValidateRuntimeParameterLiteral( - text, + relativeTestFilePath, new Map([['INTEGER_ENV', 'Value 1']]), // wrong parameter type ); @@ -157,11 +134,10 @@ describe('Validation of validateRuntimeParameterLiteral', () => { }); it('should diagnose error on missing runtime parameter value', async () => { - const text = readJvTestAsset( - 'runtime-parameter-literal/valid-text-runtime-property.jv', - ); + const relativeTestFilePath = + 'runtime-parameter-literal/valid-text-runtime-property.jv'; - await parseAndValidateRuntimeParameterLiteral(text); // don't pass parameter + await parseAndValidateRuntimeParameterLiteral(relativeTestFilePath); // don't pass parameter expect(validationAcceptorMock).toHaveBeenCalledTimes(1); expect(validationAcceptorMock).toHaveBeenCalledWith( diff --git a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/invalid-extension.lv b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/invalid-extension.lv index 70f3794d1..17199f733 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/invalid-extension.lv +++ b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/invalid-extension.lv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/valid-model.jv b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/valid-model.jv index 70f3794d1..17199f733 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/valid-model.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromFile/valid-model.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/invalid-model.jv b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/invalid-model.jv index 7abf8d0f8..1263566b0 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/invalid-model.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/invalid-model.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/valid-model.jv b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/valid-model.jv index 70f3794d1..17199f733 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/valid-model.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/extractDocumentFromString/valid-model.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/invalid-wrong-loader-type.jv b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/invalid-wrong-loader-type.jv index 037e75012..12b9e710a 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/invalid-wrong-loader-type.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/invalid-wrong-loader-type.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-document.jv b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-document.jv index 70f3794d1..17199f733 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-document.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-document.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-simplify-warning.jv b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-simplify-warning.jv index c2d191302..47ff5569a 100644 --- a/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-simplify-warning.jv +++ b/libs/interpreter-lib/test/assets/parsing-util/validateDocument/valid-simplify-warning.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from '../test-extension/TestBlockTypes.jv'; + pipeline TestPipeline { block TestExtractor oftype TestFileExtractor { diff --git a/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-integer-runtime-property.jv b/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-integer-runtime-property.jv index 34239be67..4df229fdd 100644 --- a/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-integer-runtime-property.jv +++ b/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-integer-runtime-property.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from './test-extension/TestBlockTypes.jv'; + pipeline Pipeline { block Test oftype TestProperty { integerProperty: requires INTEGER_ENV; diff --git a/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-text-runtime-property.jv b/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-text-runtime-property.jv index 66b1b7e5c..b4c1edb00 100644 --- a/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-text-runtime-property.jv +++ b/libs/interpreter-lib/test/assets/runtime-parameter-literal/valid-text-runtime-property.jv @@ -2,6 +2,8 @@ // // SPDX-License-Identifier: AGPL-3.0-only +use * from './test-extension/TestBlockTypes.jv'; + pipeline Pipeline { block Test oftype TestProperty { textProperty: requires TEXT_ENV; diff --git a/libs/language-server/src/lib/validation/checks/import-definition.spec.ts b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts index 6419fea51..60f9a71d3 100644 --- a/libs/language-server/src/lib/validation/checks/import-definition.spec.ts +++ b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts @@ -4,64 +4,36 @@ import path from 'node:path'; -import { type AstNode, type LangiumDocument, URI } from 'langium'; import { NodeFileSystem } from 'langium/node'; import { vi } from 'vitest'; import { type JayveeServices, createJayveeServices, - initializeWorkspace, isJayveeModel, } from '../../../lib'; import { - type ParseHelperOptions, createJayveeValidationProps, expectNoParserAndLexerErrors, + parseTestFileInWorkingDir, validationAcceptorMockImpl, } from '../../../test'; import { validateImportDefinition } from './import-definition'; describe('Validation of ImportDefinition', () => { + const WORKING_DIR = path.resolve(__dirname, '../../../test/assets/'); let services: JayveeServices; const validationAcceptorMock = vi.fn(validationAcceptorMockImpl); - async function parse( - relativeTestFilePath: string, - options?: ParseHelperOptions, - ): Promise> { - const testFilePath = path.resolve( - __dirname, - '../../../test/assets/', - relativeTestFilePath, - ); - const testFileUri = URI.parse(testFilePath); - const documentBuilder = services.shared.workspace.DocumentBuilder; - await initializeWorkspace(services, [ - { - name: 'projectDir', - uri: workingDir, - }, - ]); - const testDocument = - services.shared.workspace.LangiumDocuments.getDocument(testFileUri); - - assert( - testDocument !== undefined, - 'Could not load test document. Error in test setup!', - ); - - await documentBuilder.build([testDocument], options); - return testDocument; - } - - const workingDir = path.resolve(__dirname, '../../../test/assets/'); - async function parseAndValidateImportDefinition( relativeTestFilePath: string, ) { - const document = await parse(relativeTestFilePath); + const document = await parseTestFileInWorkingDir( + WORKING_DIR, + relativeTestFilePath, + services, + ); expectNoParserAndLexerErrors(document); const parsedModel = document.parseResult.value; diff --git a/libs/language-server/src/test/utils.ts b/libs/language-server/src/test/utils.ts index 6f964da63..c9eee53b2 100644 --- a/libs/language-server/src/test/utils.ts +++ b/libs/language-server/src/test/utils.ts @@ -2,14 +2,14 @@ // // SPDX-License-Identifier: AGPL-3.0-only -// eslint-disable-next-line unicorn/prefer-node-protocol -import { strict as assert } from 'assert'; import { readFileSync } from 'node:fs'; import path from 'node:path'; import { type AstNode, + type BuildOptions, type LangiumDocument, + URI, type ValidationAcceptor, } from 'langium'; import { type WorkspaceFolder } from 'vscode-languageserver-protocol'; @@ -94,3 +94,35 @@ export function createJayveeValidationProps( importResolver: importResolver, }; } + +/** + * Parses the test file and returns it. + * Uses the workingDir to initialize the workspace + * This ensures all files in the workingDir can be imported by the test file. + */ +export async function parseTestFileInWorkingDir( + workingDir: string, + relativeTestFilePath: string, + services: JayveeServices, + options?: BuildOptions, +): Promise> { + const testFilePath = path.resolve(workingDir, relativeTestFilePath); + const testFileUri = URI.parse(testFilePath); + const documentBuilder = services.shared.workspace.DocumentBuilder; + await initializeWorkspace(services, [ + { + name: 'projectDir', + uri: workingDir, + }, + ]); + const testDocument = + services.shared.workspace.LangiumDocuments.getDocument(testFileUri); + + assert( + testDocument !== undefined, + 'Could not load test document. Error in test setup!', + ); + + await documentBuilder.build([testDocument], options); + return testDocument; +} From 0a06cb25ce51e055442a78d37dfd6733c02e5bd0 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 15:48:35 +0200 Subject: [PATCH 07/13] Add license header to the JayveeImportResolver --- libs/language-server/src/lib/services/import-resolver.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/language-server/src/lib/services/import-resolver.ts b/libs/language-server/src/lib/services/import-resolver.ts index 7689a17d7..6661690fc 100644 --- a/libs/language-server/src/lib/services/import-resolver.ts +++ b/libs/language-server/src/lib/services/import-resolver.ts @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + import { AstUtils, type LangiumDocuments, type URI, UriUtils } from 'langium'; import { From a566bc48ecca2fd67de38c9b261353b7ce24bf84 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Wed, 15 May 2024 15:49:48 +0200 Subject: [PATCH 08/13] Remove uncovered test scenarios for import/export --- .../allowed-elements/invalid-unpublisheable.jv | 13 ------------- .../allowed-elements/valid-publisheable.jv | 12 ------------ .../invalid-aliased-use-published/published.jv | 5 ----- .../invalid-aliased-use-published/using.jv | 9 --------- .../main/using.jv | 9 --------- .../published.jv | 5 ----- .../invalid-use-unpublished/unpublished.jv | 5 ----- .../named-use/invalid-use-unpublished/using.jv | 9 --------- .../valid-aliased-use-published/published.jv | 5 ----- .../named-use/valid-aliased-use-published/using.jv | 9 --------- .../valid-use-aliased-published/published.jv | 7 ------- .../named-use/valid-use-aliased-published/using.jv | 9 --------- .../valid-use-directly-published/published.jv | 5 ----- .../named-use/valid-use-directly-published/using.jv | 9 --------- .../valid-use-later-published/published.jv | 7 ------- .../named-use/valid-use-later-published/using.jv | 9 --------- .../valid-use-multiple-published/published.jv | 6 ------ .../named-use/valid-use-multiple-published/using.jv | 9 --------- .../nested/published.jv | 5 ----- .../valid-use-published-deeper-dir/using.jv | 9 --------- .../invalid-aliased-use-published/published.jv | 5 ----- .../invalid-aliased-use-published/using.jv | 9 --------- .../main/using.jv | 9 --------- .../published.jv | 5 ----- .../invalid-use-unpublished/unpublished.jv | 5 ----- .../wildcard-use/invalid-use-unpublished/using.jv | 9 --------- .../valid-aliased-use-published/published.jv | 5 ----- .../valid-aliased-use-published/using.jv | 9 --------- .../valid-use-aliased-published/published.jv | 7 ------- .../valid-use-aliased-published/using.jv | 9 --------- .../valid-use-directly-published/published.jv | 5 ----- .../valid-use-directly-published/using.jv | 9 --------- .../valid-use-later-published/published.jv | 7 ------- .../wildcard-use/valid-use-later-published/using.jv | 9 --------- .../valid-use-multiple-published/published.jv | 6 ------ .../valid-use-multiple-published/using.jv | 9 --------- .../nested/published.jv | 5 ----- .../valid-use-published-deeper-dir/using.jv | 9 --------- 38 files changed, 287 deletions(-) delete mode 100644 libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv delete mode 100644 libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv delete mode 100644 libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv diff --git a/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv b/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv deleted file mode 100644 index 27a95d6d7..000000000 --- a/libs/language-server/src/test/assets/use-published/allowed-elements/invalid-unpublisheable.jv +++ /dev/null @@ -1,13 +0,0 @@ - -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish pipeline PublishedPipeline {}; // pipelines cannot be published - -pipeline UnpublishedPipeline { // no publishing within pipelines allowed - publish block PublishedBlock oftype SomeBlockType {} - publish constraint PublishedConstraint on decimal: value >= 0; - publish valuetype PublishedValueType oftype decimal {}; - publish transform PublishedTransform {}; -}; \ No newline at end of file diff --git a/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv b/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv deleted file mode 100644 index d7365cfeb..000000000 --- a/libs/language-server/src/test/assets/use-published/allowed-elements/valid-publisheable.jv +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish iotype PublishedIoType; -publish builtin constrainttype PublishedBuiltinConstraintType {}; -publish constraint PublishedConstraint on decimal: value >= 0; -publish valuetype PublishedValueType oftype decimal {}; -publish builtin blocktype PublishedBuiltinBlockType {}; -publish composite blocktype PublishedCompositeBlockType {}; -publish block PublishedBlock oftype PublishedCompositeBlockType {}; -publish transform PublishedTransform {}; \ No newline at end of file diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv deleted file mode 100644 index b6108104c..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-aliased-use-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint as AliasedB } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ Aliased ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv deleted file mode 100644 index 1e58cf897..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/main/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint } from '../unpusblished.jv'; // traversing upwards beyond entrypoint is forbidden - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv deleted file mode 100644 index d7752bcf9..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-published-higher-dir-than-entry/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv deleted file mode 100644 index 93c2bb25f..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/unpublished.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint UnpublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv b/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv deleted file mode 100644 index de0634ec0..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/invalid-use-unpublished/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { UnpublishedConstraint } from './unpusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ UnpublishedConstraint ]; // UnpublishedConstraint was not published -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv deleted file mode 100644 index 809b46c53..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-aliased-use-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint as Aliased } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ Aliased ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv deleted file mode 100644 index f0197c2c7..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/published.jv +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraintOtherName on decimal: value >= 0; - -publish PublishedConstraintOtherName as PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv deleted file mode 100644 index 1c5d6efb4..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-aliased-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv deleted file mode 100644 index 1c5d6efb4..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-directly-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv deleted file mode 100644 index 48b665a6b..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/published.jv +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraint on decimal: value >= 0; - -publish PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv deleted file mode 100644 index 1c5d6efb4..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-later-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv deleted file mode 100644 index e25ead8cf..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/published.jv +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint1 on decimal: value >= 0; -publish constraint PublishedConstraint2 on decimal: value >= 2; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv deleted file mode 100644 index 056bfeb5a..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-multiple-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint1, PublishedConstraint2 } from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint1, PublishedConstraint2 ]; -} diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/nested/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv b/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv deleted file mode 100644 index 9267d80a2..000000000 --- a/libs/language-server/src/test/assets/use-published/named-use/valid-use-published-deeper-dir/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use { PublishedConstraint } from './nested/pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv deleted file mode 100644 index 844949010..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-aliased-use-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * as AliasedB from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ Aliased.PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv deleted file mode 100644 index 67a099eed..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/main/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from '../unpusblished.jv'; // traversing upwards beyond entrypoint is forbidden - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv deleted file mode 100644 index d7752bcf9..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-published-higher-dir-than-entry/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv deleted file mode 100644 index 93c2bb25f..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/unpublished.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint UnpublishedConstraintOtherName on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv deleted file mode 100644 index be9ab55fa..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/invalid-use-unpublished/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './unpusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ UnpublishedConstraint ]; // UnpublishedConstraint was not published -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv deleted file mode 100644 index cce4c2ae2..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-aliased-use-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * as Aliased from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ Aliased.PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv deleted file mode 100644 index f0197c2c7..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/published.jv +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraintOtherName on decimal: value >= 0; - -publish PublishedConstraintOtherName as PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv deleted file mode 100644 index d6393ffb4..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-aliased-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv deleted file mode 100644 index d6393ffb4..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-directly-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv deleted file mode 100644 index 48b665a6b..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/published.jv +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -constraint PublishedConstraint on decimal: value >= 0; - -publish PublishedConstraint; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv deleted file mode 100644 index d6393ffb4..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-later-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv deleted file mode 100644 index e25ead8cf..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/published.jv +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint1 on decimal: value >= 0; -publish constraint PublishedConstraint2 on decimal: value >= 2; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv deleted file mode 100644 index 3a09d0e9c..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-multiple-published/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint1, PublishedConstraint2 ]; -} diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv deleted file mode 100644 index 0a505abec..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/nested/published.jv +++ /dev/null @@ -1,5 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -publish constraint PublishedConstraint on decimal: value >= 0; diff --git a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv b/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv deleted file mode 100644 index eac6f7ff9..000000000 --- a/libs/language-server/src/test/assets/use-published/wildcard-use/valid-use-published-deeper-dir/using.jv +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg -// -// SPDX-License-Identifier: AGPL-3.0-only - -use * from './nested/pusblished.jv'; - -valuetype UsingValueType oftype decimal { - constraints: [ PublishedConstraint ]; -} From eb859388a10f34b16fb7956c1ebe9ee6f2149393 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 16 May 2024 10:41:17 +0200 Subject: [PATCH 09/13] Fix bug where only first import in file was respected on JayveeScopeProvider --- libs/language-server/src/lib/lsp/jayvee-scope-provider.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts b/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts index 845d13a5f..fda62b3ad 100644 --- a/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts +++ b/libs/language-server/src/lib/lsp/jayvee-scope-provider.ts @@ -76,22 +76,22 @@ export class JayveeScopeProvider extends DefaultScopeProvider { for (const importDefinition of jayveeModel.imports) { const uri = this.importResover.resolveImportUri(importDefinition); if (uri === undefined) { - break; + continue; } if (importedUris.has(uri.toString())) { - break; // end recursion + continue; } importedUris.add(uri.toString()); const importedDocument = this.langiumDocuments.getDocument(uri); if (importedDocument === undefined) { - break; + continue; } const rootNode = importedDocument.parseResult.value; if (!isJayveeModel(rootNode)) { - break; + continue; } this.gatherImports(rootNode, importedUris); } From 5c897bfd240b2b98ab52759de2cc1b36c77d3283 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Thu, 16 May 2024 18:51:25 +0200 Subject: [PATCH 10/13] Remove outdated comment in import definition validation file --- .../src/lib/validation/checks/import-definition.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libs/language-server/src/lib/validation/checks/import-definition.ts b/libs/language-server/src/lib/validation/checks/import-definition.ts index 6c4cedb64..eb0408a41 100644 --- a/libs/language-server/src/lib/validation/checks/import-definition.ts +++ b/libs/language-server/src/lib/validation/checks/import-definition.ts @@ -5,10 +5,6 @@ import { type ImportDefinition } from '../../ast/generated/ast'; import { type JayveeValidationProps } from '../validation-registry'; -/** - * See https://jvalue.github.io/jayvee/docs/dev/guides/working-with-the-ast/ for why the following ESLint rule is disabled for this file. - */ - export function validateImportDefinition( importDefinition: ImportDefinition, props: JayveeValidationProps, From 620092b4d2f09ac70d28ff529da480b46de0b3b2 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Fri, 17 May 2024 11:20:53 +0200 Subject: [PATCH 11/13] Add another set of tests to ensure references are resolved across files (including transitive imports) --- .../src/lib/lsp/import-reference.spec.ts | 107 ++++++++++++++++++ ...valid-reference-to-not-existing-element.jv | 9 ++ ...valid-reference-to-not-imported-element.jv | 7 ++ .../publishing-transitive.jv | 6 + .../import-published-references/publishing.jv | 8 ++ .../valid-reference-to-element-transitive.jv | 9 ++ .../valid-reference-to-imported-element.jv | 9 ++ 7 files changed, 155 insertions(+) create mode 100644 libs/language-server/src/lib/lsp/import-reference.spec.ts create mode 100644 libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-existing-element.jv create mode 100644 libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-imported-element.jv create mode 100644 libs/language-server/src/test/assets/import-published-references/publishing-transitive.jv create mode 100644 libs/language-server/src/test/assets/import-published-references/publishing.jv create mode 100644 libs/language-server/src/test/assets/import-published-references/valid-reference-to-element-transitive.jv create mode 100644 libs/language-server/src/test/assets/import-published-references/valid-reference-to-imported-element.jv diff --git a/libs/language-server/src/lib/lsp/import-reference.spec.ts b/libs/language-server/src/lib/lsp/import-reference.spec.ts new file mode 100644 index 000000000..aa09deead --- /dev/null +++ b/libs/language-server/src/lib/lsp/import-reference.spec.ts @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +import path from 'node:path'; + +import { NodeFileSystem } from 'langium/node'; + +import { + type JayveeServices, + createJayveeServices, + isJayveeModel, +} from '../../lib'; +import { + expectNoParserAndLexerErrors, + parseTestFileInWorkingDir, +} from '../../test'; +import { type JayveeModel } from '../ast'; + +describe('References to imported elements', () => { + const WORKING_DIR = path.resolve(__dirname, '../../test/assets/'); + let services: JayveeServices; + + async function parseModel( + relativeTestFilePath: string, + ): Promise { + const document = await parseTestFileInWorkingDir( + WORKING_DIR, + relativeTestFilePath, + services, + ); + expectNoParserAndLexerErrors(document); + + const parsedModel = document.parseResult.value; + assert(isJayveeModel(parsedModel), 'Test file is not valid Jayvee model'); + return parsedModel; + } + + beforeEach(() => { + // Create language services + services = createJayveeServices(NodeFileSystem).Jayvee; + }); + + it('should resolve reference to imported element', async () => { + const relativeTestFilePath = + 'import-published-references/valid-reference-to-imported-element.jv'; + + const model = await parseModel(relativeTestFilePath); + + expect(model.pipelines.length).toEqual(1); // file contains one pipeline + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blocks = model.pipelines[0]!.blocks; + expect(blocks.length).toEqual(1); // pipeline contains one block + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const reference = blocks[0]!.type; // of an imported block type + + expect(reference.ref).toBeDefined(); + }); + + it('should resolve reference to transitively imported element', async () => { + const relativeTestFilePath = + 'import-published-references/valid-reference-to-element-transitive.jv'; + + const model = await parseModel(relativeTestFilePath); + + expect(model.pipelines.length).toEqual(1); // file contains one pipeline + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blocks = model.pipelines[0]!.blocks; + expect(blocks.length).toEqual(1); // pipeline contains one block + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const reference = blocks[0]!.type; // of an imported block type + + expect(reference.ref).toBeDefined(); + }); + + it('should not resolve reference to non-existing element', async () => { + const relativeTestFilePath = + 'import-published-references/invalid-reference-to-not-existing-element.jv'; + + const model = await parseModel(relativeTestFilePath); + + expect(model.pipelines.length).toEqual(1); // file contains one pipeline + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blocks = model.pipelines[0]!.blocks; + expect(blocks.length).toEqual(1); // pipeline contains one block + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const reference = blocks[0]!.type; // of an imported block type + + expect(reference.ref).toBeUndefined(); + }); + + it('should not resolve reference to non-imported element', async () => { + const relativeTestFilePath = + 'import-published-references/invalid-reference-to-not-imported-element.jv'; + + const model = await parseModel(relativeTestFilePath); + + expect(model.pipelines.length).toEqual(1); // file contains one pipeline + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const blocks = model.pipelines[0]!.blocks; + expect(blocks.length).toEqual(1); // pipeline contains one block + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const reference = blocks[0]!.type; // of an imported block type + + expect(reference.ref).toBeUndefined(); + }); +}); diff --git a/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-existing-element.jv b/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-existing-element.jv new file mode 100644 index 000000000..5dce66109 --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-existing-element.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './publishing.jv'; + +pipeline TestPipeline { + block UsingBlock oftype NotPublishedBlockType {} +} diff --git a/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-imported-element.jv b/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-imported-element.jv new file mode 100644 index 000000000..eccfb294e --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/invalid-reference-to-not-imported-element.jv @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +pipeline TestPipeline { + block UsingBlock oftype PublishedBlockType {} // ref to not imported element +} diff --git a/libs/language-server/src/test/assets/import-published-references/publishing-transitive.jv b/libs/language-server/src/test/assets/import-published-references/publishing-transitive.jv new file mode 100644 index 000000000..8fb024e25 --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/publishing-transitive.jv @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './publishing.jv'; +// automatically re-publishes all elements diff --git a/libs/language-server/src/test/assets/import-published-references/publishing.jv b/libs/language-server/src/test/assets/import-published-references/publishing.jv new file mode 100644 index 000000000..8230e38db --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/publishing.jv @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +builtin blocktype PublishedBlockType { + input inPort oftype None; + output outPort oftype None; +} diff --git a/libs/language-server/src/test/assets/import-published-references/valid-reference-to-element-transitive.jv b/libs/language-server/src/test/assets/import-published-references/valid-reference-to-element-transitive.jv new file mode 100644 index 000000000..ac0bb36e8 --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/valid-reference-to-element-transitive.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './publishing-transitive.jv'; + +pipeline TestPipeline { + block UsingBlock oftype PublishedBlockType {} +} diff --git a/libs/language-server/src/test/assets/import-published-references/valid-reference-to-imported-element.jv b/libs/language-server/src/test/assets/import-published-references/valid-reference-to-imported-element.jv new file mode 100644 index 000000000..428366c4d --- /dev/null +++ b/libs/language-server/src/test/assets/import-published-references/valid-reference-to-imported-element.jv @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2023 Friedrich-Alexander-Universitat Erlangen-Nurnberg +// +// SPDX-License-Identifier: AGPL-3.0-only + +use * from './publishing.jv'; + +pipeline TestPipeline { + block UsingBlock oftype PublishedBlockType {} +} From ad744b78dcef3bb1bf5ac7dd4c8c77a361322343 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Tue, 21 May 2024 14:40:05 +0200 Subject: [PATCH 12/13] Refactor import-reference tests to be less ambiguous (use test.each instead of similar test cases) --- .../src/lib/lsp/import-reference.spec.ts | 64 +++++++------------ 1 file changed, 24 insertions(+), 40 deletions(-) diff --git a/libs/language-server/src/lib/lsp/import-reference.spec.ts b/libs/language-server/src/lib/lsp/import-reference.spec.ts index aa09deead..226044271 100644 --- a/libs/language-server/src/lib/lsp/import-reference.spec.ts +++ b/libs/language-server/src/lib/lsp/import-reference.spec.ts @@ -41,26 +41,18 @@ describe('References to imported elements', () => { services = createJayveeServices(NodeFileSystem).Jayvee; }); - it('should resolve reference to imported element', async () => { - const relativeTestFilePath = - 'import-published-references/valid-reference-to-imported-element.jv'; - - const model = await parseModel(relativeTestFilePath); - - expect(model.pipelines.length).toEqual(1); // file contains one pipeline - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const blocks = model.pipelines[0]!.blocks; - expect(blocks.length).toEqual(1); // pipeline contains one block - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const reference = blocks[0]!.type; // of an imported block type - - expect(reference.ref).toBeDefined(); - }); - - it('should resolve reference to transitively imported element', async () => { - const relativeTestFilePath = - 'import-published-references/valid-reference-to-element-transitive.jv'; - + const validCases: [string, string][] = [ + // [test name, test file path] + [ + 'should resolve reference to imported element', + 'import-published-references/valid-reference-to-imported-element.jv', + ], + [ + 'should resolve reference to transitively imported element', + 'import-published-references/valid-reference-to-element-transitive.jv', + ], + ]; + test.each(validCases)('%s', async (_, relativeTestFilePath) => { const model = await parseModel(relativeTestFilePath); expect(model.pipelines.length).toEqual(1); // file contains one pipeline @@ -73,26 +65,18 @@ describe('References to imported elements', () => { expect(reference.ref).toBeDefined(); }); - it('should not resolve reference to non-existing element', async () => { - const relativeTestFilePath = - 'import-published-references/invalid-reference-to-not-existing-element.jv'; - - const model = await parseModel(relativeTestFilePath); - - expect(model.pipelines.length).toEqual(1); // file contains one pipeline - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const blocks = model.pipelines[0]!.blocks; - expect(blocks.length).toEqual(1); // pipeline contains one block - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const reference = blocks[0]!.type; // of an imported block type - - expect(reference.ref).toBeUndefined(); - }); - - it('should not resolve reference to non-imported element', async () => { - const relativeTestFilePath = - 'import-published-references/invalid-reference-to-not-imported-element.jv'; - + const invalidCases: [string, string][] = [ + // [test name, test file path] + [ + 'should not resolve reference to non-existing element', + 'import-published-references/invalid-reference-to-not-existing-element.jv', + ], + [ + 'should not resolve reference to non-imported element', + 'import-published-references/invalid-reference-to-not-imported-element.jv', + ], + ]; + test.each(invalidCases)('%s', async (_, relativeTestFilePath) => { const model = await parseModel(relativeTestFilePath); expect(model.pipelines.length).toEqual(1); // file contains one pipeline From 63c607b9370100465427fe2b5c3cd47c90612211 Mon Sep 17 00:00:00 2001 From: Georg Schwarz Date: Tue, 21 May 2024 14:45:10 +0200 Subject: [PATCH 13/13] Improve error message when file path cannot be resolved --- .../lib/validation/checks/import-definition.spec.ts | 8 ++++---- .../src/lib/validation/checks/import-definition.ts | 12 ++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/libs/language-server/src/lib/validation/checks/import-definition.spec.ts b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts index 60f9a71d3..7f9e63f72 100644 --- a/libs/language-server/src/lib/validation/checks/import-definition.spec.ts +++ b/libs/language-server/src/lib/validation/checks/import-definition.spec.ts @@ -100,13 +100,13 @@ describe('Validation of ImportDefinition', () => { expect(validationAcceptorMock).toHaveBeenNthCalledWith( 1, 'error', - 'Import cannot be resolved.', + 'Import from "not-existing-imported-file-deeper.jv" could be resolved. Check if the file exists in the given location.', expect.any(Object), ); expect(validationAcceptorMock).toHaveBeenNthCalledWith( 2, 'error', - 'Import cannot be resolved.', + 'Import from "./not-existing-imported-file-deeper.jv" could be resolved. Check if the file exists in the given location.', expect.any(Object), ); }); @@ -121,13 +121,13 @@ describe('Validation of ImportDefinition', () => { expect(validationAcceptorMock).toHaveBeenNthCalledWith( 1, 'error', - 'Import cannot be resolved.', + 'Import from "existing-imported-file.njv" could be resolved. Check if the file exists in the given location.', expect.any(Object), ); expect(validationAcceptorMock).toHaveBeenNthCalledWith( 2, 'error', - 'Import cannot be resolved.', + 'Import from "./existing-imported-file.njv" could be resolved. Check if the file exists in the given location.', expect.any(Object), ); }); diff --git a/libs/language-server/src/lib/validation/checks/import-definition.ts b/libs/language-server/src/lib/validation/checks/import-definition.ts index eb0408a41..106169ca9 100644 --- a/libs/language-server/src/lib/validation/checks/import-definition.ts +++ b/libs/language-server/src/lib/validation/checks/import-definition.ts @@ -18,9 +18,13 @@ function checkPathExists( ): void { const resolvedImport = props.importResolver.resolveImport(importDefinition); if (resolvedImport === undefined) { - props.validationContext.accept('error', 'Import cannot be resolved.', { - node: importDefinition, - property: 'path', - }); + props.validationContext.accept( + 'error', + `Import from "${importDefinition.path}" could be resolved. Check if the file exists in the given location.`, + { + node: importDefinition, + property: 'path', + }, + ); } }