updated to langium 2.1.0

regenerated project with new langium generator, reintegrated custom services, updated file structure
This commit is contained in:
JanikNex 2023-12-09 08:57:32 +01:00
parent 2fd9f9fa64
commit 9daa66344f
53 changed files with 5125 additions and 9991 deletions

178
.gitignore vendored
View file

@ -1,169 +1,13 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# *.iml
# *.ipr
# CMake
cmake-build-*/
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
.vscode/*
!.vscode/extensions.json
!.vscode/launch.json
!.vscode/tasks.json
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
*.vsix
out/
src/language/generated/
static/bundle/
static/monaco-editor-workers/
static/worker/
syntaxes/
/*.vsix

View file

@ -6,4 +6,4 @@
"recommendations": [
"langium.langium-vscode"
]
}
}

4
.vscode/launch.json vendored
View file

@ -11,6 +11,10 @@
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/**/*.js"
]
},
{

21
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,21 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build model-modeling-language",
"command": "npm run langium:generate && npm run build",
"type": "shell",
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Langium: Generate grammar and build the model-modeling-language language",
"icon": {
"color": "terminal.ansiGreen",
"id": "server-process"
}
}
]
}

View file

@ -2,7 +2,3 @@
.vscode-test/**
.gitignore
langium-quickstart.md
src
tsconfig.json
build.sh
bin

View file

@ -1,15 +0,0 @@
FROM node:20-alpine
WORKDIR /mml
RUN npm i -g yo generator-langium
RUN npm i --save-dev esbuild
RUN npm install -g @vscode/vsce
COPY --chown=node . .
RUN npm install
VOLUME /mml/out
RUN chown -R node:node /mml/out
USER node

View file

@ -1,3 +0,0 @@
#!/usr/bin/env node
require("../out/cli").default();

4
bin/cli.js Normal file
View file

@ -0,0 +1,4 @@
#!/usr/bin/env node
import main from '../out/cli/main.js';
main();

54
esbuild.mjs Normal file
View file

@ -0,0 +1,54 @@
//@ts-check
import * as esbuild from 'esbuild';
const watch = process.argv.includes('--watch');
const minify = process.argv.includes('--minify');
const success = watch ? 'Watch build succeeded' : 'Build succeeded';
function getTime() {
const date = new Date();
return `[${`${padZeroes(date.getHours())}:${padZeroes(date.getMinutes())}:${padZeroes(date.getSeconds())}`}] `;
}
function padZeroes(i) {
return i.toString().padStart(2, '0');
}
const plugins = [{
name: 'watch-plugin',
setup(build) {
build.onEnd(result => {
if (result.errors.length === 0) {
console.log(getTime() + success);
}
});
},
}];
const ctx = await esbuild.context({
// Entry points for the vscode extension and the language server
entryPoints: ['src/extension/main.ts', 'src/language/main.ts'],
outdir: 'out',
bundle: true,
target: "ES2017",
// VSCode's extension host is still using cjs, so we need to transform the code
format: 'cjs',
// To prevent confusing node, we explicitly use the `.cjs` extension
outExtension: {
'.js': '.cjs'
},
loader: { '.ts': 'ts' },
external: ['vscode'],
platform: 'node',
sourcemap: !minify,
minify,
plugins
});
if (watch) {
await ctx.watch();
} else {
await ctx.rebuild();
ctx.dispose();
}

View file

@ -2,14 +2,11 @@
"projectName": "ModelModelingLanguage",
"languages": [{
"id": "model-modeling-language",
"grammar": "src/language-server/model-modeling-language.langium",
"grammar": "src/language/model-modeling-language.langium",
"fileExtensions": [".mml"],
"textMate": {
"out": "syntaxes/model-modeling-language.tmLanguage.json"
},
"monarch": {
"out": "syntaxes/model-modeling-language.monarch.ts"
}
}],
"out": "src/language-server/generated"
"out": "src/language/generated"
}

View file

@ -5,12 +5,12 @@
This folder contains all necessary files for your language extension.
* `package.json` - the manifest file in which you declare your language support.
* `language-configuration.json` - the language configuration used in the VS Code editor, defining the tokens that are used for comments and brackets.
* `src/extension.ts` - the main code of the extension, which is responsible for launching a language server and client.
* `src/language-server/model-modeling-language.langium` - the grammar definition of your language.
* `src/language-server/main.ts` - the entry point of the language server process.
* `src/language-server/model-modeling-language-module.ts` - the dependency injection module of your language implementation. Use this to register overridden and added services.
* `src/language-server/model-modeling-language-validator.ts` - an example validator. You should change it to reflect the semantics of your language.
* `src/cli/index.ts` - the entry point of the command line interface (CLI) of your language.
* `src/extension/main.ts` - the main code of the extension, which is responsible for launching a language server and client.
* `src/language/model-modeling-language.langium` - the grammar definition of your language.
* `src/language/main.ts` - the entry point of the language server process.
* `src/language/model-modeling-language-module.ts` - the dependency injection module of your language implementation. Use this to register overridden and added services.
* `src/language/model-modeling-language-validator.ts` - an example validator. You should change it to reflect the semantics of your language.
* `src/cli/main.ts` - the entry point of the command line interface (CLI) of your language.
* `src/cli/generator.ts` - the code generator used by the CLI to write output files from DSL documents.
* `src/cli/cli-util.ts` - utility code for the CLI.
@ -21,12 +21,12 @@ This folder contains all necessary files for your language extension.
* Press `F5` to open a new window with your extension loaded.
* Create a new file with a file name suffix matching your language.
* Verify that syntax highlighting, validation, completion etc. are working as expected.
* Run `./bin/cli` to see options for the CLI; `./bin/cli generate <file>` generates code for a given DSL file.
* Run `node ./bin/cli` to see options for the CLI; `node ./bin/cli generate <file>` generates code for a given DSL file.
## Make changes
* Run `npm run watch` to have the TypeScript compiler run automatically after every change of the source files.
* Run `npm run langium:watch` to have the Langium generator run automatically afer every change of the grammar declaration.
* Run `npm run langium:watch` to have the Langium generator run automatically after every change of the grammar declaration.
* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.

9126
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,87 +1,78 @@
{
"name": "model-modeling-language",
"displayName": "Model modeling language",
"description": "A VS Code extension that implements a Domain Specific Language for describing metamodels.",
"version": "0.0.1",
"repository": "https://github.com/JanikNex/model-modeling-language",
"publisher": "Janik Rapp",
"engines": {
"vscode": "^1.67.0"
},
"categories": [
"Programming Languages"
],
"contributes": {
"languages": [
{
"id": "model-modeling-language",
"aliases": [
"Model modeling language",
"model-modeling-language"
],
"extensions": [
".mml"
],
"configuration": "./language-configuration.json"
}
"name": "model-modeling-language",
"displayName": "Model modeling language",
"description": "A VS Code extension that implements a Domain Specific Language for describing metamodels.",
"version": "0.0.2",
"repository": "https://github.com/JanikNex/model-modeling-language",
"publisher": "Janik Rapp",
"files": [
"bin"
],
"grammars": [
{
"language": "model-modeling-language",
"scopeName": "source.model-modeling-language",
"path": "./syntaxes/model-modeling-language.tmLanguage.json"
}
]
},
"activationEvents": [
"onLanguage:model-modeling-language"
],
"files": [
"bin",
"out",
"src",
"syntaxes",
"language-configuration.json",
"langium-config.json",
"tsconfig.json",
".eslintrc.json"
],
"bin": {
"model-modeling-language-cli": "./bin/cli"
},
"main": "./out/extension.js",
"scripts": {
"vscode:prepublish": "npm run build && npm run lint",
"build": "tsc -b tsconfig.json",
"watch": "tsc -b tsconfig.json -watch",
"lint": "eslint src test --ext ts --no-error-on-unmatched-pattern",
"langium:generate": "langium generate",
"langium:watch": "langium generate --watch",
"fullbuild": "npm run langium:generate && vsce package",
"build:ls": "esbuild ./out/language-server/main-browser.js --bundle --format=esm --sourcemap --outfile=./out/public/mmlServerWorker.js",
"fullbuild:ls": "vsce package --no-dependencies && npm run build:ls"
},
"dependencies": {
"chalk": "~4.1.2",
"commander": "~11.0.0",
"langium": "~1.1.0",
"uuid": "^9.0.0",
"@types/uuid": "^9.0.0",
"vscode-languageclient": "~8.0.2",
"vscode-languageserver": "~8.0.2"
},
"devDependencies": {
"@types/node": "~16.18.11",
"@types/vscode": "~1.67.0",
"@vscode/vsce": "^2.21.0",
"@typescript-eslint/eslint-plugin": "~5.51.0",
"@typescript-eslint/parser": "~5.51.0",
"esbuild": "^0.17.18",
"eslint": "~8.33.0",
"eslint-plugin-header": "^3.1.1",
"langium-cli": "~1.1.0",
"typescript": "~4.9.5",
"vitest": "^0.34.6",
"shx": "^0.3.4"
}
"type": "module",
"scripts": {
"build": "tsc -b tsconfig.json && node esbuild.mjs",
"watch": "concurrently -n tsc,esbuild -c blue,yellow \"tsc -b tsconfig.json --watch\" \"node esbuild.mjs --watch\"",
"lint": "eslint src --ext ts",
"langium:generate": "langium generate",
"langium:watch": "langium generate --watch",
"vscode:prepublish": "npm run build && npm run lint",
"package": "vsce package",
"fullbuild": "npm run langium:generate && vsce package"
},
"dependencies": {
"@types/uuid": "^9.0.0",
"uuid": "^9.0.0",
"langium": "~2.1.0",
"vscode-languageclient": "~9.0.1",
"vscode-languageserver": "~9.0.1",
"chalk": "~5.3.0",
"commander": "~11.0.0"
},
"devDependencies": {
"@types/node": "~16.18.41",
"@typescript-eslint/parser": "~6.4.1",
"@typescript-eslint/eslint-plugin": "~6.4.1",
"@vscode/vsce": "^2.21.0",
"eslint": "~8.47.0",
"langium-cli": "~2.1.0",
"typescript": "~5.1.6",
"@types/vscode": "~1.67.0",
"concurrently": "~8.2.1",
"esbuild": "~0.19.2",
"vitest": "^0.34.6"
},
"engines": {
"vscode": "^1.67.0",
"node": ">=16.0.0"
},
"categories": [
"Programming Languages"
],
"contributes": {
"languages": [
{
"id": "model-modeling-language",
"aliases": [
"Model Modeling Language",
"model-modeling-language"
],
"extensions": [".mml"],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "model-modeling-language",
"scopeName": "source.model-modeling-language",
"path": "syntaxes/model-modeling-language.tmLanguage.json"
}
]
},
"activationEvents": [
"onLanguage:model-modeling-language"
],
"main": "./out/extension/main.cjs",
"bin": {
"model-modeling-language-cli": "./bin/cli.js"
}
}

View file

@ -1,8 +1,8 @@
import type {AstNode, LangiumDocument, LangiumServices} from 'langium';
import {URI} from 'langium';
import chalk from 'chalk';
import path, {resolve} from 'path';
import fs from 'fs';
import {AstNode, LangiumDocument, LangiumServices} from 'langium';
import {URI} from 'vscode-uri';
import * as path from 'node:path';
import * as fs from 'node:fs';
/**
* Types of path targets
@ -54,7 +54,7 @@ export function getFilesInDirRecursive(targetName: string, extensions: string[])
export async function getFiles(dir: string): Promise<string[]> {
const dirents = await fs.promises.readdir(dir, {withFileTypes: true});
const files = await Promise.all(dirents.map((dirent) => {
const res = resolve(dir, dirent.name);
const res = path.resolve(dir, dirent.name);
return dirent.isDirectory() ? getFiles(res) : res;
}));
return Array.prototype.concat(...files) as string[];
@ -86,7 +86,7 @@ export async function extractDocuments(fileNames: string[], services: LangiumSer
documents.push(document)
}
await services.shared.workspace.DocumentBuilder.build(documents, {validationChecks: 'all'});
await services.shared.workspace.DocumentBuilder.build(documents, {validation: true});
let containsError = false;
for (const document of documents) {

View file

@ -1,10 +1,10 @@
import fs from 'fs';
import type {Model} from '../language/generated/ast.js';
import * as fs from 'node:fs';
import {CompositeGeneratorNode, NL, toString} from 'langium';
import path from 'path';
import {Model} from '../language-server/generated/ast';
import {extractDestinationAndName} from './cli-util';
import {serializeModel} from "../language-server/generator/mml-serializer";
import {ModelModelingLanguageServices} from "../language-server/model-modeling-language-module";
import * as path from 'node:path';
import {extractDestinationAndName} from './cli-util.js';
import {serializeModel} from "../language/serializer/mml-serializer.js";
import {ModelModelingLanguageServices} from "../language/model-modeling-language-module.js";
export function generateSingleModelSerialization(model: Model, filePath: string, destination: string | undefined, services: ModelModelingLanguageServices): string {
const data = extractDestinationAndName(filePath, destination);
@ -44,3 +44,4 @@ export function generateMultiModelSerialization(models: Model[], filePath: strin
fs.writeFileSync(generatedFilePath, toString(fileNode));
return generatedFilePath;
}

View file

@ -1,15 +1,21 @@
import type { Model } from '../language/generated/ast.js';
import chalk from 'chalk';
import {Command} from 'commander';
import {Model} from '../language-server/generated/ast';
import {ModelModelingLanguageLanguageMetaData} from '../language-server/generated/module';
import {createModelModelingLanguageServices} from '../language-server/model-modeling-language-module';
import {extractAstNode, extractAstNodes, GeneratorTargetType, getFiles, getTargetType} from './cli-util';
import {generateMultiModelSerialization, generateSingleModelSerialization} from './generator';
import {NodeFileSystem} from 'langium/node';
import path from "path";
import { Command } from 'commander';
import { ModelModelingLanguageLanguageMetaData } from '../language/generated/module.js';
import { createModelModelingLanguageServices } from '../language/model-modeling-language-module.js';
import {extractAstNode, extractAstNodes, GeneratorTargetType, getFiles, getTargetType} from './cli-util.js';
import { NodeFileSystem } from 'langium/node';
import * as url from 'node:url';
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import {generateMultiModelSerialization, generateSingleModelSerialization} from "./generator.js";
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const packagePath = path.resolve(__dirname, '..', '..', 'package.json');
const packageContent = await fs.readFile(packagePath, 'utf-8');
export const generateAction = async (targetName: string, opts: GenerateOptions): Promise<void> => {
const services = createModelModelingLanguageServices(NodeFileSystem).mmlServices;
const services = createModelModelingLanguageServices(NodeFileSystem).MmlServices;
const targetType: GeneratorTargetType = getTargetType(targetName)
let generatedFilePath = ""
if (targetType == GeneratorTargetType.FILE) {
@ -31,12 +37,10 @@ export type GenerateOptions = {
destination?: string;
}
export default function (): void {
export default function(): void {
const program = new Command();
program
// eslint-disable-next-line @typescript-eslint/no-var-requires
.version(require('../../package.json').version);
program.version(JSON.parse(packageContent).version);
const fileExtensions = ModelModelingLanguageLanguageMetaData.fileExtensions.join(', ');
program

View file

@ -1,8 +1,7 @@
import type { LanguageClientOptions, ServerOptions} from 'vscode-languageclient/node.js';
import * as vscode from 'vscode';
import * as path from 'path';
import {
LanguageClient, LanguageClientOptions, ServerOptions, TransportKind
} from 'vscode-languageclient/node';
import * as path from 'node:path';
import { LanguageClient, TransportKind } from 'vscode-languageclient/node.js';
let client: LanguageClient;
@ -20,7 +19,7 @@ export function deactivate(): Thenable<void> | undefined {
}
function startLanguageClient(context: vscode.ExtensionContext): LanguageClient {
const serverModule = context.asAbsolutePath(path.join('out', 'language-server', 'main'));
const serverModule = context.asAbsolutePath(path.join('out', 'language', 'main.cjs'));
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging.
// By setting `process.env.DEBUG_BREAK` to a truthy value, the language server will wait until a debugger is attached.
@ -48,7 +47,7 @@ function startLanguageClient(context: vscode.ExtensionContext): LanguageClient {
// Create the language client and start the client.
const client = new LanguageClient(
'model-modeling-language',
'Model modeling language',
'Model Modeling Language',
serverOptions,
clientOptions
);

View file

@ -1,978 +0,0 @@
/******************************************************************************
* This file was generated by langium-cli 1.1.0.
* DO NOT EDIT MANUALLY!
******************************************************************************/
/* eslint-disable */
import { AstNode, AbstractAstReflection, Reference, ReferenceInfo, TypeMetaData } from 'langium';
export type AbstractElement = Class | Enum | Interface;
export const AbstractElement = 'AbstractElement';
export function isAbstractElement(item: unknown): item is AbstractElement {
return reflection.isInstance(item, AbstractElement);
}
export type ArithExpr = BinaryExpression | EnumValueExpr | FunctionVariableSelectorExpr | ValueExpr | VariableValueExpr;
export const ArithExpr = 'ArithExpr';
export function isArithExpr(item: unknown): item is ArithExpr {
return reflection.isInstance(item, ArithExpr);
}
export type DataType = 'bool' | 'double' | 'float' | 'int' | 'string';
export type FunctionStatement = FunctionAssignment | FunctionCall | FunctionLoop | FunctionMacroCall;
export const FunctionStatement = 'FunctionStatement';
export function isFunctionStatement(item: unknown): item is FunctionStatement {
return reflection.isInstance(item, FunctionStatement);
}
export type InstanceStatement = FunctionAssignment | FunctionCall | FunctionMacroCall;
export const InstanceStatement = 'InstanceStatement';
export function isInstanceStatement(item: unknown): item is InstanceStatement {
return reflection.isInstance(item, InstanceStatement);
}
export type MacroStatement = MacroAssignStatement | MacroAttributeStatement;
export const MacroStatement = 'MacroStatement';
export function isMacroStatement(item: unknown): item is MacroStatement {
return reflection.isInstance(item, MacroStatement);
}
export type Statement = Attribute | CReference;
export const Statement = 'Statement';
export function isStatement(item: unknown): item is Statement {
return reflection.isInstance(item, Statement);
}
export type ValueExpr = BoolExpr | NumberExpr | StringExpr;
export const ValueExpr = 'ValueExpr';
export function isValueExpr(item: unknown): item is ValueExpr {
return reflection.isInstance(item, ValueExpr);
}
export type Variable = FunctionVariable | TypedVariable | UntypedVariable;
export const Variable = 'Variable';
export function isVariable(item: unknown): item is Variable {
return reflection.isInstance(item, Variable);
}
export interface Attribute extends AstNode {
readonly $container: Class | Interface;
readonly $type: 'Attribute';
defaultValue?: ArithExpr
modifiers?: AttributeModifiers
name: string
type: AttributeType
}
export const Attribute = 'Attribute';
export function isAttribute(item: unknown): item is Attribute {
return reflection.isInstance(item, Attribute);
}
export interface AttributeModifiers extends AstNode {
readonly $container: Attribute;
readonly $type: 'AttributeModifiers';
derived: boolean
id: boolean
ordered: boolean
readonly: boolean
transient: boolean
unique: boolean
unsettable: boolean
volatile: boolean
}
export const AttributeModifiers = 'AttributeModifiers';
export function isAttributeModifiers(item: unknown): item is AttributeModifiers {
return reflection.isInstance(item, AttributeModifiers);
}
export interface AttributeType extends AstNode {
readonly $container: Attribute;
readonly $type: 'AttributeType';
etype?: Reference<Enum>
ptype?: DataType
}
export const AttributeType = 'AttributeType';
export function isAttributeType(item: unknown): item is AttributeType {
return reflection.isInstance(item, AttributeType);
}
export interface BinaryExpression extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'BinaryExpression';
left: ArithExpr
operator: '%' | '*' | '+' | '-' | '/' | '^'
right: ArithExpr
}
export const BinaryExpression = 'BinaryExpression';
export function isBinaryExpression(item: unknown): item is BinaryExpression {
return reflection.isInstance(item, BinaryExpression);
}
export interface BoolExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'BoolExpr';
value: boolean
}
export const BoolExpr = 'BoolExpr';
export function isBoolExpr(item: unknown): item is BoolExpr {
return reflection.isInstance(item, BoolExpr);
}
export interface Class extends AstNode {
readonly $container: Package;
readonly $type: 'Class';
abstract: boolean
body: Array<Statement>
extendedClasses: Array<Reference<Class>>
implementedInterfaces: Array<Reference<Interface>>
name: string
}
export const Class = 'Class';
export function isClass(item: unknown): item is Class {
return reflection.isInstance(item, Class);
}
export interface CReference extends AstNode {
readonly $container: Class | Interface;
readonly $type: 'CReference';
modifiers?: ReferenceModifiers
multiplicity?: Multiplicity
name: string
opposite?: OppositeAnnotation
type: Reference<Class>
}
export const CReference = 'CReference';
export function isCReference(item: unknown): item is CReference {
return reflection.isInstance(item, CReference);
}
export interface Enum extends AstNode {
readonly $container: Package;
readonly $type: 'Enum';
entries: Array<EnumEntry>
name: string
}
export const Enum = 'Enum';
export function isEnum(item: unknown): item is Enum {
return reflection.isInstance(item, Enum);
}
export interface EnumEntry extends AstNode {
readonly $container: Enum;
readonly $type: 'EnumEntry';
name: string
value?: ValueExpr
}
export const EnumEntry = 'EnumEntry';
export function isEnumEntry(item: unknown): item is EnumEntry {
return reflection.isInstance(item, EnumEntry);
}
export interface EnumValueExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'EnumValueExpr';
val: Reference<EnumEntry>
}
export const EnumValueExpr = 'EnumValueExpr';
export function isEnumValueExpr(item: unknown): item is EnumValueExpr {
return reflection.isInstance(item, EnumValueExpr);
}
export interface FunctionArgument extends AstNode {
readonly $container: FunctionCall | FunctionMacroCall;
readonly $type: 'FunctionArgument';
ref?: Reference<Variable>
value?: ArithExpr
}
export const FunctionArgument = 'FunctionArgument';
export function isFunctionArgument(item: unknown): item is FunctionArgument {
return reflection.isInstance(item, FunctionArgument);
}
export interface FunctionAssignment extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IInstance | InstanceLoop;
readonly $type: 'FunctionAssignment';
call: FunctionCall | FunctionMacroCall
select?: Reference<TypedVariable>
var: FunctionVariable | TypedVariable
}
export const FunctionAssignment = 'FunctionAssignment';
export function isFunctionAssignment(item: unknown): item is FunctionAssignment {
return reflection.isInstance(item, FunctionAssignment);
}
export interface FunctionCall extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IInstance | InstanceLoop;
readonly $type: 'FunctionCall';
args: Array<FunctionArgument>
func: Reference<IFunction>
}
export const FunctionCall = 'FunctionCall';
export function isFunctionCall(item: unknown): item is FunctionCall {
return reflection.isInstance(item, FunctionCall);
}
export interface FunctionLoop extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IInstance | InstanceLoop;
readonly $type: 'FunctionLoop';
lower: number
statements: Array<FunctionStatement>
upper: number
var: UntypedVariable
}
export const FunctionLoop = 'FunctionLoop';
export function isFunctionLoop(item: unknown): item is FunctionLoop {
return reflection.isInstance(item, FunctionLoop);
}
export interface FunctionMacroCall extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IInstance | InstanceLoop;
readonly $type: 'FunctionMacroCall';
args: Array<FunctionArgument>
macro: Reference<IMacro>
}
export const FunctionMacroCall = 'FunctionMacroCall';
export function isFunctionMacroCall(item: unknown): item is FunctionMacroCall {
return reflection.isInstance(item, FunctionMacroCall);
}
export interface FunctionReturn extends AstNode {
readonly $container: IFunction;
readonly $type: 'FunctionReturn';
val?: ImplicitlyTypedValue
var?: Reference<TypedVariable>
}
export const FunctionReturn = 'FunctionReturn';
export function isFunctionReturn(item: unknown): item is FunctionReturn {
return reflection.isInstance(item, FunctionReturn);
}
export interface FunctionVariable extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IMacro | InstanceLoop | MacroInstance;
readonly $type: 'FunctionVariable';
name: string
}
export const FunctionVariable = 'FunctionVariable';
export function isFunctionVariable(item: unknown): item is FunctionVariable {
return reflection.isInstance(item, FunctionVariable);
}
export interface FunctionVariableSelectorExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'FunctionVariableSelectorExpr';
val: Reference<TypedVariable>
}
export const FunctionVariableSelectorExpr = 'FunctionVariableSelectorExpr';
export function isFunctionVariableSelectorExpr(item: unknown): item is FunctionVariableSelectorExpr {
return reflection.isInstance(item, FunctionVariableSelectorExpr);
}
export interface IFunction extends AstNode {
readonly $container: Model;
readonly $type: 'IFunction';
name: string
parameter: Array<TypedVariable>
returnsVar: boolean
statements: Array<FunctionReturn> | Array<FunctionStatement>
typing?: VariableType
}
export const IFunction = 'IFunction';
export function isIFunction(item: unknown): item is IFunction {
return reflection.isInstance(item, IFunction);
}
export interface IInstance extends AstNode {
readonly $container: Model;
readonly $type: 'IInstance';
name: string
statements: Array<InstanceLoop | InstanceStatement>
}
export const IInstance = 'IInstance';
export function isIInstance(item: unknown): item is IInstance {
return reflection.isInstance(item, IInstance);
}
export interface IMacro extends AstNode {
readonly $container: Model;
readonly $type: 'IMacro';
instances: Array<MacroInstance>
name: string
parameter: Array<TypedVariable>
}
export const IMacro = 'IMacro';
export function isIMacro(item: unknown): item is IMacro {
return reflection.isInstance(item, IMacro);
}
export interface ImplicitlyTypedValue extends AstNode {
readonly $container: FunctionReturn;
readonly $type: 'ImplicitlyTypedValue';
val: ArithExpr
}
export const ImplicitlyTypedValue = 'ImplicitlyTypedValue';
export function isImplicitlyTypedValue(item: unknown): item is ImplicitlyTypedValue {
return reflection.isInstance(item, ImplicitlyTypedValue);
}
export interface Import extends AstNode {
readonly $container: Model;
readonly $type: 'Import';
aliases: Array<ImportAlias>
target: string
}
export const Import = 'Import';
export function isImport(item: unknown): item is Import {
return reflection.isInstance(item, Import);
}
export interface ImportAlias extends AstNode {
readonly $container: Import;
readonly $type: 'ImportAlias';
alias: string
ref: Reference<Package>
}
export const ImportAlias = 'ImportAlias';
export function isImportAlias(item: unknown): item is ImportAlias {
return reflection.isInstance(item, ImportAlias);
}
export interface InstanceLoop extends AstNode {
readonly $container: IInstance;
readonly $type: 'InstanceLoop';
ivar: UntypedVariable
ref: Reference<CReference>
statements: Array<InstanceStatement>
var: Reference<TypedVariable>
}
export const InstanceLoop = 'InstanceLoop';
export function isInstanceLoop(item: unknown): item is InstanceLoop {
return reflection.isInstance(item, InstanceLoop);
}
export interface Interface extends AstNode {
readonly $container: Package;
readonly $type: 'Interface';
abstract: boolean
body: Array<Statement>
extendedInterfaces: Array<Reference<Interface>>
name: string
}
export const Interface = 'Interface';
export function isInterface(item: unknown): item is Interface {
return reflection.isInstance(item, Interface);
}
export interface MacroAssignStatement extends AstNode {
readonly $container: MacroInstance;
readonly $type: 'MacroAssignStatement';
cref: Reference<CReference>
instance: Reference<TypedVariable>
}
export const MacroAssignStatement = 'MacroAssignStatement';
export function isMacroAssignStatement(item: unknown): item is MacroAssignStatement {
return reflection.isInstance(item, MacroAssignStatement);
}
export interface MacroAttributeStatement extends AstNode {
readonly $container: MacroInstance;
readonly $type: 'MacroAttributeStatement';
attr: Reference<Attribute>
value: ArithExpr
}
export const MacroAttributeStatement = 'MacroAttributeStatement';
export function isMacroAttributeStatement(item: unknown): item is MacroAttributeStatement {
return reflection.isInstance(item, MacroAttributeStatement);
}
export interface MacroInstance extends AstNode {
readonly $container: IMacro;
readonly $type: 'MacroInstance';
iVar?: Reference<TypedVariable>
nInst?: TypedVariable
statements: Array<MacroStatement>
}
export const MacroInstance = 'MacroInstance';
export function isMacroInstance(item: unknown): item is MacroInstance {
return reflection.isInstance(item, MacroInstance);
}
export interface Model extends AstNode {
readonly $type: 'Model';
functions: Array<IFunction>
imports: Array<Import>
instances: Array<IInstance>
macros: Array<IMacro>
packages: Array<Package>
}
export const Model = 'Model';
export function isModel(item: unknown): item is Model {
return reflection.isInstance(item, Model);
}
export interface Multiplicity extends AstNode {
readonly $container: CReference;
readonly $type: 'Multiplicity';
mult: MultiplicitySpec
upperMult?: MultiplicitySpec
}
export const Multiplicity = 'Multiplicity';
export function isMultiplicity(item: unknown): item is Multiplicity {
return reflection.isInstance(item, Multiplicity);
}
export interface MultiplicitySpec extends AstNode {
readonly $container: Multiplicity;
readonly $type: 'MultiplicitySpec';
n: boolean
n_0: boolean
num?: number
}
export const MultiplicitySpec = 'MultiplicitySpec';
export function isMultiplicitySpec(item: unknown): item is MultiplicitySpec {
return reflection.isInstance(item, MultiplicitySpec);
}
export interface NumberExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'NumberExpr';
value: number
}
export const NumberExpr = 'NumberExpr';
export function isNumberExpr(item: unknown): item is NumberExpr {
return reflection.isInstance(item, NumberExpr);
}
export interface OppositeAnnotation extends AstNode {
readonly $container: CReference;
readonly $type: 'OppositeAnnotation';
reference: Reference<CReference>
}
export const OppositeAnnotation = 'OppositeAnnotation';
export function isOppositeAnnotation(item: unknown): item is OppositeAnnotation {
return reflection.isInstance(item, OppositeAnnotation);
}
export interface Package extends AstNode {
readonly $container: Model | Package;
readonly $type: 'Package';
body: Array<AbstractElement>
name: string
subPackages: Array<Package>
}
export const Package = 'Package';
export function isPackage(item: unknown): item is Package {
return reflection.isInstance(item, Package);
}
export interface ReferenceModifiers extends AstNode {
readonly $container: CReference;
readonly $type: 'ReferenceModifiers';
derived: boolean
ordered: boolean
readonly: boolean
resolve: boolean
transient: boolean
unique: boolean
unsettable: boolean
volatile: boolean
}
export const ReferenceModifiers = 'ReferenceModifiers';
export function isReferenceModifiers(item: unknown): item is ReferenceModifiers {
return reflection.isInstance(item, ReferenceModifiers);
}
export interface StringExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'StringExpr';
value: string
}
export const StringExpr = 'StringExpr';
export function isStringExpr(item: unknown): item is StringExpr {
return reflection.isInstance(item, StringExpr);
}
export interface TypedVariable extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IMacro | InstanceLoop | MacroInstance;
readonly $type: 'TypedVariable';
name: string
typing: VariableType
}
export const TypedVariable = 'TypedVariable';
export function isTypedVariable(item: unknown): item is TypedVariable {
return reflection.isInstance(item, TypedVariable);
}
export interface UntypedVariable extends AstNode {
readonly $container: FunctionAssignment | FunctionLoop | IFunction | IMacro | InstanceLoop | MacroInstance;
readonly $type: 'UntypedVariable';
name: string
}
export const UntypedVariable = 'UntypedVariable';
export function isUntypedVariable(item: unknown): item is UntypedVariable {
return reflection.isInstance(item, UntypedVariable);
}
export interface VariableType extends AstNode {
readonly $container: IFunction | TypedVariable;
readonly $type: 'VariableType';
dtype?: DataType
type?: Reference<AbstractElement>
}
export const VariableType = 'VariableType';
export function isVariableType(item: unknown): item is VariableType {
return reflection.isInstance(item, VariableType);
}
export interface VariableValueExpr extends AstNode {
readonly $container: Attribute | BinaryExpression | EnumEntry | FunctionArgument | ImplicitlyTypedValue | MacroAttributeStatement;
readonly $type: 'VariableValueExpr';
val: Reference<Variable>
}
export const VariableValueExpr = 'VariableValueExpr';
export function isVariableValueExpr(item: unknown): item is VariableValueExpr {
return reflection.isInstance(item, VariableValueExpr);
}
export interface ModelModelingLanguageAstType {
AbstractElement: AbstractElement
ArithExpr: ArithExpr
Attribute: Attribute
AttributeModifiers: AttributeModifiers
AttributeType: AttributeType
BinaryExpression: BinaryExpression
BoolExpr: BoolExpr
CReference: CReference
Class: Class
Enum: Enum
EnumEntry: EnumEntry
EnumValueExpr: EnumValueExpr
FunctionArgument: FunctionArgument
FunctionAssignment: FunctionAssignment
FunctionCall: FunctionCall
FunctionLoop: FunctionLoop
FunctionMacroCall: FunctionMacroCall
FunctionReturn: FunctionReturn
FunctionStatement: FunctionStatement
FunctionVariable: FunctionVariable
FunctionVariableSelectorExpr: FunctionVariableSelectorExpr
IFunction: IFunction
IInstance: IInstance
IMacro: IMacro
ImplicitlyTypedValue: ImplicitlyTypedValue
Import: Import
ImportAlias: ImportAlias
InstanceLoop: InstanceLoop
InstanceStatement: InstanceStatement
Interface: Interface
MacroAssignStatement: MacroAssignStatement
MacroAttributeStatement: MacroAttributeStatement
MacroInstance: MacroInstance
MacroStatement: MacroStatement
Model: Model
Multiplicity: Multiplicity
MultiplicitySpec: MultiplicitySpec
NumberExpr: NumberExpr
OppositeAnnotation: OppositeAnnotation
Package: Package
ReferenceModifiers: ReferenceModifiers
Statement: Statement
StringExpr: StringExpr
TypedVariable: TypedVariable
UntypedVariable: UntypedVariable
ValueExpr: ValueExpr
Variable: Variable
VariableType: VariableType
VariableValueExpr: VariableValueExpr
}
export class ModelModelingLanguageAstReflection extends AbstractAstReflection {
getAllTypes(): string[] {
return ['AbstractElement', 'ArithExpr', 'Attribute', 'AttributeModifiers', 'AttributeType', 'BinaryExpression', 'BoolExpr', 'CReference', 'Class', 'Enum', 'EnumEntry', 'EnumValueExpr', 'FunctionArgument', 'FunctionAssignment', 'FunctionCall', 'FunctionLoop', 'FunctionMacroCall', 'FunctionReturn', 'FunctionStatement', 'FunctionVariable', 'FunctionVariableSelectorExpr', 'IFunction', 'IInstance', 'IMacro', 'ImplicitlyTypedValue', 'Import', 'ImportAlias', 'InstanceLoop', 'InstanceStatement', 'Interface', 'MacroAssignStatement', 'MacroAttributeStatement', 'MacroInstance', 'MacroStatement', 'Model', 'Multiplicity', 'MultiplicitySpec', 'NumberExpr', 'OppositeAnnotation', 'Package', 'ReferenceModifiers', 'Statement', 'StringExpr', 'TypedVariable', 'UntypedVariable', 'ValueExpr', 'Variable', 'VariableType', 'VariableValueExpr'];
}
protected override computeIsSubtype(subtype: string, supertype: string): boolean {
switch (subtype) {
case Attribute:
case CReference: {
return this.isSubtype(Statement, supertype);
}
case BinaryExpression:
case EnumValueExpr:
case FunctionVariableSelectorExpr:
case ValueExpr:
case VariableValueExpr: {
return this.isSubtype(ArithExpr, supertype);
}
case BoolExpr:
case NumberExpr:
case StringExpr: {
return this.isSubtype(ValueExpr, supertype);
}
case Class:
case Enum:
case Interface: {
return this.isSubtype(AbstractElement, supertype);
}
case FunctionAssignment:
case FunctionCall:
case FunctionMacroCall: {
return this.isSubtype(FunctionStatement, supertype) || this.isSubtype(InstanceStatement, supertype);
}
case FunctionLoop: {
return this.isSubtype(FunctionStatement, supertype);
}
case FunctionVariable:
case TypedVariable:
case UntypedVariable: {
return this.isSubtype(Variable, supertype);
}
case MacroAssignStatement:
case MacroAttributeStatement: {
return this.isSubtype(MacroStatement, supertype);
}
default: {
return false;
}
}
}
getReferenceType(refInfo: ReferenceInfo): string {
const referenceId = `${refInfo.container.$type}:${refInfo.property}`;
switch (referenceId) {
case 'AttributeType:etype': {
return Enum;
}
case 'Class:extendedClasses':
case 'CReference:type': {
return Class;
}
case 'Class:implementedInterfaces':
case 'Interface:extendedInterfaces': {
return Interface;
}
case 'EnumValueExpr:val': {
return EnumEntry;
}
case 'FunctionArgument:ref':
case 'VariableValueExpr:val': {
return Variable;
}
case 'FunctionAssignment:select':
case 'FunctionReturn:var':
case 'FunctionVariableSelectorExpr:val':
case 'InstanceLoop:var':
case 'MacroAssignStatement:instance':
case 'MacroInstance:iVar': {
return TypedVariable;
}
case 'FunctionCall:func': {
return IFunction;
}
case 'FunctionMacroCall:macro': {
return IMacro;
}
case 'ImportAlias:ref': {
return Package;
}
case 'InstanceLoop:ref':
case 'MacroAssignStatement:cref':
case 'OppositeAnnotation:reference': {
return CReference;
}
case 'MacroAttributeStatement:attr': {
return Attribute;
}
case 'VariableType:type': {
return AbstractElement;
}
default: {
throw new Error(`${referenceId} is not a valid reference id.`);
}
}
}
getTypeMetaData(type: string): TypeMetaData {
switch (type) {
case 'AttributeModifiers': {
return {
name: 'AttributeModifiers',
mandatory: [
{ name: 'derived', type: 'boolean' },
{ name: 'id', type: 'boolean' },
{ name: 'ordered', type: 'boolean' },
{ name: 'readonly', type: 'boolean' },
{ name: 'transient', type: 'boolean' },
{ name: 'unique', type: 'boolean' },
{ name: 'unsettable', type: 'boolean' },
{ name: 'volatile', type: 'boolean' }
]
};
}
case 'BoolExpr': {
return {
name: 'BoolExpr',
mandatory: [
{ name: 'value', type: 'boolean' }
]
};
}
case 'Class': {
return {
name: 'Class',
mandatory: [
{ name: 'abstract', type: 'boolean' },
{ name: 'body', type: 'array' },
{ name: 'extendedClasses', type: 'array' },
{ name: 'implementedInterfaces', type: 'array' }
]
};
}
case 'Enum': {
return {
name: 'Enum',
mandatory: [
{ name: 'entries', type: 'array' }
]
};
}
case 'FunctionCall': {
return {
name: 'FunctionCall',
mandatory: [
{ name: 'args', type: 'array' }
]
};
}
case 'FunctionLoop': {
return {
name: 'FunctionLoop',
mandatory: [
{ name: 'statements', type: 'array' }
]
};
}
case 'FunctionMacroCall': {
return {
name: 'FunctionMacroCall',
mandatory: [
{ name: 'args', type: 'array' }
]
};
}
case 'IFunction': {
return {
name: 'IFunction',
mandatory: [
{ name: 'parameter', type: 'array' },
{ name: 'returnsVar', type: 'boolean' },
{ name: 'statements', type: 'array' }
]
};
}
case 'IInstance': {
return {
name: 'IInstance',
mandatory: [
{ name: 'statements', type: 'array' }
]
};
}
case 'IMacro': {
return {
name: 'IMacro',
mandatory: [
{ name: 'instances', type: 'array' },
{ name: 'parameter', type: 'array' }
]
};
}
case 'Import': {
return {
name: 'Import',
mandatory: [
{ name: 'aliases', type: 'array' }
]
};
}
case 'InstanceLoop': {
return {
name: 'InstanceLoop',
mandatory: [
{ name: 'statements', type: 'array' }
]
};
}
case 'Interface': {
return {
name: 'Interface',
mandatory: [
{ name: 'abstract', type: 'boolean' },
{ name: 'body', type: 'array' },
{ name: 'extendedInterfaces', type: 'array' }
]
};
}
case 'MacroInstance': {
return {
name: 'MacroInstance',
mandatory: [
{ name: 'statements', type: 'array' }
]
};
}
case 'Model': {
return {
name: 'Model',
mandatory: [
{ name: 'functions', type: 'array' },
{ name: 'imports', type: 'array' },
{ name: 'instances', type: 'array' },
{ name: 'macros', type: 'array' },
{ name: 'packages', type: 'array' }
]
};
}
case 'MultiplicitySpec': {
return {
name: 'MultiplicitySpec',
mandatory: [
{ name: 'n', type: 'boolean' },
{ name: 'n_0', type: 'boolean' }
]
};
}
case 'Package': {
return {
name: 'Package',
mandatory: [
{ name: 'body', type: 'array' },
{ name: 'subPackages', type: 'array' }
]
};
}
case 'ReferenceModifiers': {
return {
name: 'ReferenceModifiers',
mandatory: [
{ name: 'derived', type: 'boolean' },
{ name: 'ordered', type: 'boolean' },
{ name: 'readonly', type: 'boolean' },
{ name: 'resolve', type: 'boolean' },
{ name: 'transient', type: 'boolean' },
{ name: 'unique', type: 'boolean' },
{ name: 'unsettable', type: 'boolean' },
{ name: 'volatile', type: 'boolean' }
]
};
}
default: {
return {
name: type,
mandatory: []
};
}
}
}
}
export const reflection = new ModelModelingLanguageAstReflection();

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
/******************************************************************************
* This file was generated by langium-cli 1.1.0.
* DO NOT EDIT MANUALLY!
******************************************************************************/
import { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, LanguageMetaData, Module } from 'langium';
import { ModelModelingLanguageAstReflection } from './ast';
import { ModelModelingLanguageGrammar } from './grammar';
export const ModelModelingLanguageLanguageMetaData: LanguageMetaData = {
languageId: 'model-modeling-language',
fileExtensions: ['.mml'],
caseInsensitive: false
};
export const ModelModelingLanguageGeneratedSharedModule: Module<LangiumSharedServices, LangiumGeneratedSharedServices> = {
AstReflection: () => new ModelModelingLanguageAstReflection()
};
export const ModelModelingLanguageGeneratedModule: Module<LangiumServices, LangiumGeneratedServices> = {
Grammar: () => ModelModelingLanguageGrammar(),
LanguageMetaData: () => ModelModelingLanguageLanguageMetaData,
parser: {}
};

View file

@ -1,35 +0,0 @@
import {DocumentState, EmptyFileSystem, startLanguageServer} from 'langium';
import {BrowserMessageReader, BrowserMessageWriter, createConnection} from 'vscode-languageserver/browser';
import {createModelModelingLanguageServices} from "./model-modeling-language-module";
import {Diagnostic, NotificationType} from "vscode-languageserver";
import {Model} from "./generated/ast";
import {serializeModel} from "./generator/mml-serializer";
declare const self: DedicatedWorkerGlobalScope;
/* browser specific setup code */
const messageReader = new BrowserMessageReader(self);
const messageWriter = new BrowserMessageWriter(self);
const connection = createConnection(messageReader, messageWriter);
// Inject the shared services and language-specific services
const {shared, mmlServices} = createModelModelingLanguageServices({connection, ...EmptyFileSystem});
// Start the language server with the shared services
startLanguageServer(shared);
// Send a notification with the serialized AST after every document change
type DocumentChange = { uri: string, content: string, diagnostics: Diagnostic[] };
const documentChangeNotification = new NotificationType<DocumentChange>('browser/DocumentChange');
shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, documents => {
for (const document of documents) {
const module = document.parseResult.value as Model;
connection.sendNotification(documentChangeNotification, {
uri: document.uri.toString(),
content: serializeModel(module, mmlServices),
diagnostics: document.diagnostics ?? []
});
}
});

View file

@ -1,7 +1,7 @@
import { startLanguageServer } from 'langium';
import { NodeFileSystem } from 'langium/node';
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node';
import { createModelModelingLanguageServices } from './model-modeling-language-module';
import { createConnection, ProposedFeatures } from 'vscode-languageserver/node.js';
import { createModelModelingLanguageServices } from './model-modeling-language-module.js';
// Create a connection to the client
const connection = createConnection(ProposedFeatures.all);

View file

@ -8,11 +8,11 @@ import {
LangiumServices,
MaybePromise
} from "langium";
import * as ast from "./generated/ast";
import {EnumEntry, EnumValueExpr} from "./generated/ast";
import * as ast from "./generated/ast.js";
import {Attribute, CReference, EnumEntry, EnumValueExpr} from "./generated/ast.js";
import {CodeAction, CodeActionKind, CodeActionParams, Command, Diagnostic} from "vscode-languageserver";
import {IssueCodes} from "./model-modeling-language-validator";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils";
import {IssueCodes} from "./model-modeling-language-validator.js";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils.js";
/**
* The CodeActionProvider deals with code actions (also known as quick fixes).
@ -64,7 +64,7 @@ export class ModelModelingLanguageCodeActionProvider implements CodeActionProvid
const text = document.textDocument.getText(diagnostic.range);
if (rootCst && text) {
const cstNode = findLeafNodeAtOffset(rootCst, offset);
const container = getContainerOfType(cstNode?.element, ast.isAttribute);
const container: Attribute | undefined = getContainerOfType(cstNode?.astNode, ast.isAttribute);
if (container && container.$cstNode && container.defaultValue != undefined) {
let newType: string = "";
if (ModelModelingLanguageUtils.isStringArithExpr(container.defaultValue)) {
@ -136,7 +136,7 @@ export class ModelModelingLanguageCodeActionProvider implements CodeActionProvid
const rootCst = document.parseResult.value.$cstNode;
if (rootCst) {
const cstNode = findLeafNodeAtOffset(rootCst, offset);
const container = getContainerOfType(cstNode?.element, ast.isCReference);
const container: CReference | undefined = getContainerOfType(cstNode?.astNode, ast.isCReference);
if (container && container.$cstNode) {
if (container.opposite != undefined && container.opposite.reference.ref != undefined) {
const oppositeNode = container.opposite.reference.ref;

View file

@ -22,7 +22,7 @@ import {
isModel,
isPackage,
isTypedVariable
} from "./generated/ast";
} from "./generated/ast.js";
/**
* The Formatter deals with formatting MML code in the file. More precisely, correct

View file

@ -1,21 +1,19 @@
import {
createDefaultModule,
createDefaultSharedModule,
import type {
DefaultSharedModuleContext,
inject,
LangiumServices,
LangiumSharedServices,
Module,
PartialLangiumServices
} from 'langium';
import {ModelModelingLanguageGeneratedModule, ModelModelingLanguageGeneratedSharedModule} from './generated/module';
import {ModelModelingLanguageValidator, registerValidationChecks} from './model-modeling-language-validator';
import {ModelModelingLanguageScopeComputation} from "./model-modeling-language-scope-computation";
import {ModelModelingLanguageSemanticTokenProvider} from "./model-modeling-language-semantic-token-provider";
import {ModelModelingLanguageCodeActionProvider} from "./model-modeling-language-code-action-provider";
import {ModelModelingLanguageFormatter} from "./model-modeling-language-formatter";
import {ModelModelingLanguageScopeProvider} from "./model-modeling-language-scope-provider";
import {ModelModelingLanguageCompletionProvider} from "./model-modeling-language-completion-provider";
import {createDefaultModule, createDefaultSharedModule, inject} from 'langium';
import {ModelModelingLanguageGeneratedModule, ModelModelingLanguageGeneratedSharedModule} from './generated/module.js';
import {ModelModelingLanguageValidator, registerValidationChecks} from './model-modeling-language-validator.js';
import {ModelModelingLanguageScopeComputation} from "./model-modeling-language-scope-computation.js";
import {ModelModelingLanguageScopeProvider} from "./model-modeling-language-scope-provider.js";
import {ModelModelingLanguageSemanticTokenProvider} from "./model-modeling-language-semantic-token-provider.js";
import {ModelModelingLanguageCodeActionProvider} from "./model-modeling-language-code-action-provider.js";
import {ModelModelingLanguageFormatter} from "./model-modeling-language-formatter.js";
import {ModelModelingLanguageCompletionProvider} from "./model-modeling-language-completion-provider.js";
/**
* Declaration of custom services - add your own service classes here.
@ -23,6 +21,16 @@ import {ModelModelingLanguageCompletionProvider} from "./model-modeling-language
export type ModelModelingLanguageAddedServices = {
validation: {
ModelModelingLanguageValidator: ModelModelingLanguageValidator
},
references: {
ScopeComputation: ModelModelingLanguageScopeComputation,
ScopeProvider: ModelModelingLanguageScopeProvider,
},
lsp: {
SemanticTokenProvider: ModelModelingLanguageSemanticTokenProvider,
CodeActionProvider: ModelModelingLanguageCodeActionProvider,
Formatter: ModelModelingLanguageFormatter,
CompletionProvider: ModelModelingLanguageCompletionProvider
}
}
@ -70,18 +78,18 @@ export const ModelModelingLanguageModule: Module<ModelModelingLanguageServices,
*/
export function createModelModelingLanguageServices(context: DefaultSharedModuleContext): {
shared: LangiumSharedServices,
mmlServices: ModelModelingLanguageServices
MmlServices: ModelModelingLanguageServices
} {
const shared = inject(
createDefaultSharedModule(context),
ModelModelingLanguageGeneratedSharedModule,
ModelModelingLanguageGeneratedSharedModule
);
const mmlServices = inject(
const MmlServices = inject(
createDefaultModule({shared}),
ModelModelingLanguageGeneratedModule,
ModelModelingLanguageModule
);
shared.ServiceRegistry.register(mmlServices);
registerValidationChecks(mmlServices);
return {shared, mmlServices};
shared.ServiceRegistry.register(MmlServices);
registerValidationChecks(MmlServices);
return {shared, MmlServices};
}

View file

@ -1,6 +1,6 @@
import {AstNodeDescription, DefaultScopeComputation, LangiumDocument, streamAllContents} from "langium";
import {isClass, isCReference, isEnum, isInterface, isPackage} from "./generated/ast";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils";
import {isClass, isCReference, isEnum, isInterface, isPackage} from "./generated/ast.js";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils.js";
/**
* The ScopeComputation deals with the calculation of the scope. At this point we implement

View file

@ -43,10 +43,10 @@ import {
isModel,
TypedVariable,
Variable
} from "./generated/ast";
} from "./generated/ast.js";
import {URI} from "vscode-uri";
import {ModelModelingLanguageServices} from "./model-modeling-language-module";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils";
import {ModelModelingLanguageServices} from "./model-modeling-language-module.js";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils.js";
/**
* The ScopeProvider searches scopes and is used to calculate custom scopes for individual

View file

@ -28,7 +28,7 @@ import {
isPackage,
isStringExpr,
isTypedVariable
} from "./generated/ast";
} from "./generated/ast.js";
import {SemanticTokenTypes} from "vscode-languageserver";
/**

View file

@ -32,7 +32,7 @@ import {
TypedVariable,
Variable,
VariableValueExpr
} from "./generated/ast";
} from "./generated/ast.js";
/**
* A collection of various functions, which are used by different components.

View file

@ -40,10 +40,10 @@ import {
Package,
TypedVariable,
VariableType
} from './generated/ast';
import type {ModelModelingLanguageServices} from './model-modeling-language-module';
} from './generated/ast.js';
import type {ModelModelingLanguageServices} from './model-modeling-language-module.js';
import {URI} from "vscode-uri";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils";
import {ModelModelingLanguageUtils} from "./model-modeling-language-utils.js";
/**
* Register custom validation checks.

View file

@ -105,7 +105,7 @@ VariableType:
Variable:
UntypedVariable | TypedVariable | FunctionVariable;
UntypedVariable:
name=ID;

View file

@ -18,10 +18,10 @@ import {
Multiplicity,
Package,
ReferenceModifiers
} from "../generated/ast";
import {MmlReferenceStorage} from "./mml-reference-storage";
import {ModelModelingLanguageUtils} from "../model-modeling-language-utils";
import {MmlSerializerContext} from "./mml-serializer-context";
} from "../generated/ast.js";
import {MmlReferenceStorage} from "./mml-reference-storage.js";
import {ModelModelingLanguageUtils} from "../model-modeling-language-utils.js";
import {MmlSerializerContext} from "./mml-serializer-context.js";
/**
* These dataclasses define the structure of the serialized metamodel output.

View file

@ -1,4 +1,4 @@
import {ObjectInstance} from "./mml-instance-templates";
import {ObjectInstance} from "./mml-instance-templates.js";
import {v4 as uuidv4} from 'uuid';
/**

View file

@ -21,11 +21,11 @@ import {
MacroInstance,
Model,
Variable
} from "../generated/ast";
import {MmlSerializerContext} from "./mml-serializer-context";
import {zip} from "./utils";
import {MmlReferenceStorage} from "./mml-reference-storage";
import {MmlInstanceRegistry} from "./mml-instance-registry";
} from "../generated/ast.js";
import {MmlSerializerContext} from "./mml-serializer-context.js";
import {zip} from "./utils.js";
import {MmlReferenceStorage} from "./mml-reference-storage.js";
import {MmlInstanceRegistry} from "./mml-instance-registry.js";
/**
* These dataclasses define the structure of the serialized instance output.
@ -213,8 +213,8 @@ export class ObjectInstance {
public addAttribute(attr: MacroAttributeStatement, context: MmlSerializerContext, referenceStorage: MmlReferenceStorage) {
if (attr.attr.ref != undefined) {
var val;
var isEnumType = false;
let val;
let isEnumType = false;
if (isEnumValueExpr(attr.value) && attr.value.val.ref != undefined) {
val = referenceStorage.getNodeReferenceId(attr.value.val.ref)
isEnumType = true;

View file

@ -6,13 +6,13 @@ import {AstNode, AstNodeLocator, getDocument, Reference} from "langium";
export class MmlReferenceStorage {
private referenceMap: Map<string, AstNode> = new Map<string, AstNode>;
private nodeMap: Map<AstNode, string> = new Map<AstNode, string>;
private _astLocator;
private readonly _astLocator;
constructor(locator: AstNodeLocator) {
this._astLocator = locator;
}
private storeReference(ref: Reference<AstNode>): string {
private storeReference(ref: Reference): string {
const node = ref.ref;
if (node != undefined) {
const referenceId = this.getNodeReferenceId(node);
@ -31,7 +31,7 @@ export class MmlReferenceStorage {
return doc.uri.path + node.$type + path;
}
public resolveReference(ref: Reference<AstNode>): string {
public resolveReference(ref: Reference): string {
const node = ref.ref;
if (node != undefined && ref.$nodeDescription != undefined) {
const lookup = this.nodeMap.get(node);

View file

@ -9,7 +9,7 @@ import {
isStringExpr,
isVariableValueExpr,
Variable
} from "../generated/ast";
} from "../generated/ast.js";
/**
* The MmlSerializerContext is used for variable storage and resolution.

View file

@ -1,10 +1,10 @@
import {Model} from "../generated/ast";
import {MmlReferenceStorage} from "./mml-reference-storage";
import {SerializedModel} from "./mml-entity-templates";
import {ModelModelingLanguageServices} from "../model-modeling-language-module";
import {SerializedInstances} from "./mml-instance-templates";
import {MmlInstanceRegistry} from "./mml-instance-registry";
import {jsonReplacer} from "./utils";
import {Model} from "../generated/ast.js";
import {MmlReferenceStorage} from "./mml-reference-storage.js";
import {SerializedModel} from "./mml-entity-templates.js";
import {ModelModelingLanguageServices} from "../model-modeling-language-module.js";
import {SerializedInstances} from "./mml-instance-templates.js";
import {MmlInstanceRegistry} from "./mml-instance-registry.js";
import {jsonReplacer} from "./utils.js";
/**
* Function to interpret and serialize a given Mml model

View file

@ -1,31 +0,0 @@
// Monarch syntax highlighting for the model-modeling-language language.
export default {
keywords: [
'@opposite','abstract','as','attribute','bool','class','derived','double','enum','extends','false','float','for','function','id','implements','import','in','instance','int','interface','macro','ordered','package','readonly','reference','resolve','return','returns','string','transient','true','tuple','unique','unsettable','using','volatile'
],
operators: [
'%','*','+',',','-','->','.','..','/',':',';','=','^'
],
symbols: /%|\(|\)|\*|\+|,|-|->|\.|\.\.|/|:|;|=|\[|\]|\^|\{|\}/,
tokenizer: {
initial: [
{ regex: /-?\d+\.\d+/, action: {"token":"number"} },
{ regex: /-?\d+/, action: {"token":"number"} },
{ regex: /"[^"]*"/, action: {"token":"string"} },
{ regex: /[a-zA-Z_][\w_]*/, action: { cases: { '@keywords': {"token":"keyword"}, '@default': {"token":"string"} }} },
{ include: '@whitespace' },
{ regex: /@symbols/, action: { cases: { '@operators': {"token":"operator"}, '@default': {"token":""} }} },
],
whitespace: [
{ regex: /\s+/, action: {"token":"white"} },
{ regex: /\/\*/, action: {"token":"comment","next":"@comment"} },
{ regex: /[^:]\/\/[^\n\r]*/, action: {"token":"comment"} },
],
comment: [
{ regex: /[^\/\*]+/, action: {"token":"comment"} },
{ regex: /\*\//, action: {"token":"comment","next":"@pop"} },
{ regex: /[\/\*]/, action: {"token":"comment"} },
],
}
};

View file

@ -1,61 +0,0 @@
{
"name": "model-modeling-language",
"scopeName": "source.model-modeling-language",
"fileTypes": [
".mml"
],
"patterns": [
{
"include": "#comments"
},
{
"name": "keyword.control.model-modeling-language",
"match": "\\b(abstract|as|attribute|bool|class|derived|double|enum|extends|false|float|for|function|id|implements|import|in|instance|int|interface|macro|ordered|package|readonly|reference|resolve|return|returns|string|transient|true|tuple|unique|unsettable|using|volatile)\\b|\\B(@opposite)\\b"
},
{
"name": "string.quoted.double.model-modeling-language",
"begin": "\"",
"end": "\"",
"patterns": [
{
"include": "#string-character-escape"
}
]
}
],
"repository": {
"comments": {
"patterns": [
{
"name": "comment.block.model-modeling-language",
"begin": "/\\*",
"beginCaptures": {
"0": {
"name": "punctuation.definition.comment.model-modeling-language"
}
},
"end": "\\*/",
"endCaptures": {
"0": {
"name": "punctuation.definition.comment.model-modeling-language"
}
}
},
{
"begin": "[^:]//",
"beginCaptures": {
"1": {
"name": "punctuation.whitespace.comment.leading.model-modeling-language"
}
},
"end": "(?=$)",
"name": "comment.line.model-modeling-language"
}
]
},
"string-character-escape": {
"name": "constant.character.escape.model-modeling-language",
"match": "\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|u\\{[0-9A-Fa-f]+\\}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.|$)"
}
}
}

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {getArithExprEval} from "./testutils";
import {getArithExprEval} from "./testutils.js";
describe('Arith Expression evaluator', () => {
test('Addition 1', async () => {

View file

@ -1,5 +1,5 @@
import {describe, expect, test} from "vitest";
import {getModel} from "./testutils";
import {describe, test} from "vitest";
import {expectParserErrorLength, getModel} from "./testutils.js";
describe('Test model definition parser', () => {
@ -8,7 +8,7 @@ describe('Test model definition parser', () => {
import "path/to/other/file";
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test import with alias', async () => {
@ -16,7 +16,7 @@ describe('Test model definition parser', () => {
import "path/to/other/file" using Test.Model as Test;
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -25,7 +25,7 @@ describe('Test model definition parser', () => {
/// Test comment
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test multiline comment', async () => {
@ -33,7 +33,7 @@ describe('Test model definition parser', () => {
/* Test comment */
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -43,7 +43,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test package with subpackages', async () => {
@ -57,7 +57,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class', async () => {
@ -68,7 +68,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test interface', async () => {
@ -79,7 +79,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test interface that extends interface', async () => {
@ -92,7 +92,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test interface that extends multiple interfaces', async () => {
@ -107,7 +107,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test enum', async () => {
@ -120,7 +120,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test enum with default values', async () => {
@ -133,7 +133,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test abstract class', async () => {
@ -144,7 +144,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class that implements interface', async () => {
@ -157,7 +157,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class that extends class', async () => {
@ -170,7 +170,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class that extends abstract class', async () => {
@ -183,7 +183,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test abstract class that extends class', async () => {
@ -196,7 +196,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test abstract class that extends abstract class', async () => {
@ -209,7 +209,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with string attribute', async () => {
@ -221,7 +221,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with string attribute and value', async () => {
@ -233,7 +233,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with int attribute', async () => {
@ -245,7 +245,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with int attribute and value', async () => {
@ -257,7 +257,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with double attribute', async () => {
@ -269,7 +269,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -282,7 +282,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -295,7 +295,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -308,7 +308,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with bool attribute', async () => {
@ -320,7 +320,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with bool attribute and value', async () => {
@ -332,7 +332,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with enum attribute', async () => {
@ -349,7 +349,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with enum attribute and value', async () => {
@ -366,7 +366,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -379,7 +379,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -392,7 +392,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -405,7 +405,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -418,7 +418,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference', async () => {
@ -433,7 +433,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -449,7 +449,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference and multiplicity 2', async () => {
@ -464,7 +464,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference and multiplicity 3', async () => {
@ -479,7 +479,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference and multiplicity 4', async () => {
@ -494,7 +494,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference and multiplicity 5', async () => {
@ -509,7 +509,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with reference and multiplicity 6', async () => {
@ -524,7 +524,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -540,7 +540,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -556,7 +556,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with annotated reference', async () => {
@ -573,7 +573,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
test('Test class with bi-annotated reference', async () => {
@ -591,7 +591,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -609,7 +609,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -627,7 +627,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -645,7 +645,7 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});
@ -656,6 +656,6 @@ describe('Test model definition parser', () => {
}
`);
expect(model.$document.parseResult.parserErrors.length).toEqual(0);
expectParserErrorLength(model).toEqual(0);
});*/
});

View file

@ -1,5 +1,5 @@
import {describe, test} from "vitest";
import {getSerialization} from "./testutils";
import {getSerialization} from "./testutils.js";
describe('Serializer tests', () => {
test('test', async () => {

View file

@ -1,15 +1,17 @@
import {ArithExpr, Attribute, Class, Model} from "../src/language-server/generated/ast";
import {ArithExpr, Attribute, Class, Model} from "../src/language/generated/ast.js";
import {parseDocument, validationHelper, ValidationResult} from "langium/test";
import {AstNode, EmptyFileSystem} from "langium";
import {AstNode, EmptyFileSystem, LangiumDocument} from "langium";
import {serializeModel} from "../src/language/serializer/mml-serializer.js";
import {MmlSerializerContext} from "../src/language/serializer/mml-serializer-context.js";
import {
createModelModelingLanguageServices,
ModelModelingLanguageServices
} from "../src/language-server/model-modeling-language-module";
import {serializeModel} from "../src/language-server/generator/mml-serializer";
import {MmlSerializerContext} from "../src/language-server/generator/mml-serializer-context";
} from "../src/language/model-modeling-language-module.js";
import {Assertion, expect} from "vitest";
import {Diagnostic} from "vscode-languageserver";
function getServices(): ModelModelingLanguageServices {
return createModelModelingLanguageServices(EmptyFileSystem).mmlServices;
return createModelModelingLanguageServices(EmptyFileSystem).MmlServices;
}
export async function getModel(code: string): Promise<Model> {
@ -69,4 +71,21 @@ export function findNode(node: AstNode, path: string): AstNode | undefined {
export async function getSerialization(code: string): Promise<string> {
const model: Model = await getModel(code);
return serializeModel(model, getServices());
}
export function expectErrorCode(validationResult: ValidationResult<AstNode>, idx: number): Assertion {
const diagnostic: Diagnostic | undefined = validationResult.diagnostics.at(idx);
if (diagnostic == undefined) {
throw new RangeError("Diagnostic index out of range!");
}
return expect(diagnostic.code);
}
export function expectParserErrorLength(model: Model): Assertion {
const document: LangiumDocument | undefined = model.$document;
if (document == undefined) {
throw new Error("Model with undefined document!");
}
const parserErrorLength = document.parseResult.parserErrors.length;
return expect(parserErrorLength);
}

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('ArithExpr validator tests', () => {
test('Validator should compute correct string concat type', async () => {
@ -126,7 +126,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 2', async () => {
@ -139,7 +139,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 3', async () => {
@ -152,7 +152,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 4', async () => {
@ -165,7 +165,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 5', async () => {
@ -178,7 +178,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 6', async () => {
@ -191,7 +191,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice unsupported operation 7', async () => {
@ -204,7 +204,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should notice upsupported operation 8', async () => {
@ -217,7 +217,7 @@ describe('ArithExpr validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ArithExpressionUnsupportedOperation);
});
test('Validator should compute correct multiplied string type', async () => {

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Class validator tests', () => {
@ -13,7 +13,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ClassSelfExtension);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ClassSelfExtension);
});
test('Validator should notice non-unique extends 1', async () => {
@ -27,7 +27,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.DuplicateClassExtension);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.DuplicateClassExtension);
});
test('Validator should notice non-unique extends 2', async () => {
@ -43,7 +43,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.DuplicateClassExtension);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.DuplicateClassExtension);
});
test('Validator should notice interface self extends 1', async () => {
@ -55,7 +55,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InterfaceSelfExtension);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InterfaceSelfExtension);
});
test('Validator should notice interface self extends 2', async () => {
@ -69,7 +69,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InterfaceSelfExtension);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InterfaceSelfExtension);
});
test('Validator should notice non-unique implements 1', async () => {
@ -83,7 +83,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.DuplicateClassImplements);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.DuplicateClassImplements);
});
test('Validator should notice non-unique implements 2', async () => {
@ -99,7 +99,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.DuplicateClassImplements);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.DuplicateClassImplements);
});
test('Validator should notice non-unique class statement names 1', async () => {
@ -113,7 +113,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ClassStatementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ClassStatementNameNotUnique);
});
test('Validator should notice non-unique class statement names 2', async () => {
@ -129,9 +129,9 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(3);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ClassStatementNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expect(validationResult.diagnostics.at(2).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ClassStatementNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 2).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice non-unique class statement names 3', async () => {
@ -147,8 +147,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ClassStatementNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ClassStatementNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice non-unique interface statement names 1', async () => {
@ -162,7 +162,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
});
test('Validator should notice non-unique interface statement names 2', async () => {
@ -178,9 +178,9 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(3);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expect(validationResult.diagnostics.at(2).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 2).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice non-unique interface statement names 3', async () => {
@ -196,8 +196,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InterfaceStatementNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice invalid multiplicities 1', async () => {
@ -212,8 +212,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InvalidMultiplicity);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InvalidMultiplicity);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice invalid multiplicities 2', async () => {
@ -228,8 +228,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InvalidMultiplicity);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InvalidMultiplicity);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice invalid multiplicities 3', async () => {
@ -244,8 +244,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InvalidMultiplicity);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InvalidMultiplicity);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositeAnnotationMissing);
});
test('Validator should notice missing opposites opposite annotation', async () => {
@ -262,8 +262,8 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.OppositeAnnotationMissing);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.OppositesOppositeAnnotationMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.OppositeAnnotationMissing);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.OppositesOppositeAnnotationMissing);
});
test('Validator should notice non-matching opposite annotations', async () => {
@ -285,7 +285,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.OppositeAnnotationDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.OppositeAnnotationDoesNotMatch);
});
test('Validator should notice non-matching attribute type 1', async () => {
@ -298,7 +298,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 2', async () => {
@ -311,7 +311,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 3', async () => {
@ -324,7 +324,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 4', async () => {
@ -341,7 +341,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 5', async () => {
@ -354,7 +354,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 6', async () => {
@ -367,7 +367,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 7', async () => {
@ -380,7 +380,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 8', async () => {
@ -397,7 +397,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 9', async () => {
@ -410,7 +410,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 10', async () => {
@ -423,7 +423,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 11', async () => {
@ -440,7 +440,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 12', async () => {
@ -453,7 +453,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 13', async () => {
@ -466,7 +466,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 14', async () => {
@ -479,7 +479,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should notice non-matching attribute type 15', async () => {
@ -496,7 +496,7 @@ describe('Class validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.AttributeTypeDoesNotMatch);
});
test('Validator should succeed', async () => {

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Enum validator tests', () => {
@ -15,7 +15,7 @@ describe('Enum validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.EnumTypeNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.EnumTypeNotUnique);
});
test('Validator should notice non-unique enum type 2', async () => {
@ -29,7 +29,7 @@ describe('Enum validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.EnumTypeNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.EnumTypeNotUnique);
});
test('Validator should notice non-unique enum type 3', async () => {
@ -43,7 +43,7 @@ describe('Enum validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.EnumTypeNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.EnumTypeNotUnique);
});
test('Validator should succeed 1', async () => {

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Function validator tests', () => {
test('Validator should notice non-unique function name', async () => {
@ -22,7 +22,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionNameNotUnique);
});
test('Validator should notice missing return statement', async () => {
@ -41,7 +41,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionReturnStatementMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionReturnStatementMissing);
});
test('Validator should notice missing return signature', async () => {
@ -61,7 +61,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionReturnTypeSignatureMissing);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionReturnTypeSignatureMissing);
});
test('Validator should notice non-matching return statement signature pair', async () => {
@ -81,7 +81,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionReturnSignatureTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionReturnSignatureTypeMismatch);
});
test('Validator should notice missing macro call parameters', async () => {
@ -101,7 +101,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentLengthMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentLengthMismatch);
});
test('Validator should notice to many macro call parameters', async () => {
@ -121,7 +121,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentLengthMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentLengthMismatch);
});
test('Validator should notice macro call parameter type mismatch 1', async () => {
@ -141,7 +141,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});
test('Validator should notice macro call parameter type mismatch 2', async () => {
@ -164,8 +164,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});
test('Validator should notice macro call parameter type mismatch 3', async () => {
@ -188,8 +188,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});
test('Validator should notice macro call parameter type mismatch 4', async () => {
@ -212,7 +212,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});
test('Validator should notice missing function call parameters', async () => {
@ -235,7 +235,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentLengthMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentLengthMismatch);
});
test('Validator should notice to many function call parameters', async () => {
@ -258,7 +258,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentLengthMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentLengthMismatch);
});
test('Validator should notice function call parameter type mismatch 1', async () => {
@ -281,7 +281,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice function call parameter type mismatch 2', async () => {
@ -307,8 +307,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice function call parameter type mismatch 3', async () => {
@ -334,8 +334,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice function call parameter type mismatch 4', async () => {
@ -361,7 +361,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice tuple assignment of macro call instance', async () => {
@ -386,7 +386,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
});
test('Validator should notice variable assignment of macro call tuple', async () => {
@ -411,7 +411,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
});
test('Validator should notice macro call assignment type mismatch 1', async () => {
@ -436,7 +436,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
});
test('Validator should notice macro call assignment type mismatch 2', async () => {
@ -461,7 +461,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
});
test('Validator should notice assignment of void type function', async () => {
@ -487,7 +487,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentWithVoidFunction);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentWithVoidFunction);
});
test('Validator should notice tuple assignment of function call', async () => {
@ -513,7 +513,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
});
test('Validator should notice assignment instance selector on function call', async () => {
@ -539,8 +539,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionAssignmentWithVoidFunction);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTupleHandlingMismatch);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionAssignmentWithVoidFunction);
});
test('Validator should notice function call assignment type mismatch 1', async () => {
@ -567,7 +567,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
});
test('Validator should notice function call assignment type mismatch 2', async () => {
@ -597,7 +597,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
});
test('Validator should notice function call assignment type mismatch 3', async () => {
@ -624,7 +624,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionAssignmentTypeMismatch);
});
test('Validator should notice function loop boundary mismatch', async () => {
@ -651,7 +651,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionLoopBoundaryMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionLoopBoundaryMismatch);
});
test('Validator should notice non-unique function variables 1', async () => {
@ -673,7 +673,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice non-unique function variables 2', async () => {
@ -703,7 +703,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice non-unique function variables 3', async () => {
@ -733,7 +733,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice non-unique function variables 4', async () => {
@ -762,7 +762,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice non-unique function variables 5', async () => {
@ -792,7 +792,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice non-unique function variables 6', async () => {
@ -821,7 +821,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionVariableNameNotUnique);
});
test('Validator should notice invalid function variable selector expr selector', async () => {
@ -853,9 +853,9 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(3);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expect(validationResult.diagnostics.at(2).code).toEqual(IssueCodes.InvalidTupleSelectorInParameter);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 2).toEqual(IssueCodes.InvalidTupleSelectorInParameter);
});
test('Validator should notice invalid function variable selector type in function call', async () => {
@ -887,7 +887,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice invalid selector on non-function variable in function call', async () => {
@ -919,8 +919,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice invalid function variable selector type in macro call', async () => {
@ -952,7 +952,7 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionCallArgumentTypeMismatch);
});
test('Validator should notice invalid selector on non-function variable in macro call', async () => {
@ -984,8 +984,8 @@ describe('Function validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Instance validator tests', () => {
test('Validator should notice non-unique function name', async () => {
@ -12,7 +12,7 @@ describe('Instance validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InstanceNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InstanceNameNotUnique);
});
test('Validator should notice non-matching for loop type', async () => {
@ -50,7 +50,7 @@ describe('Instance validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.FunctionMacroCallArgumentTypeMismatch);
});
test('Validator should succeed', async () => {

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Macro validator tests', () => {
test('Validator should notice non-unique macro name', async () => {
@ -24,7 +24,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroNameNotUnique);
});
test('Validator should notice non-unique macro variable name 1', async () => {
@ -50,8 +50,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.MacroVariableNameNotUnique);
});
test('Validator should notice non-unique macro variable name 2', async () => {
@ -77,7 +77,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroVariableNameNotUnique);
});
test('Validator should notice non-unique macro variable name 3', async () => {
@ -103,8 +103,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.MacroVariableNameNotUnique);
});
test('Validator should notice non-unique macro variable name 4', async () => {
@ -130,10 +130,10 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(4);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expect(validationResult.diagnostics.at(2).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expect(validationResult.diagnostics.at(3).code).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 2).toEqual(IssueCodes.MacroVariableNameNotUnique);
expectErrorCode(validationResult, 3).toEqual(IssueCodes.MacroVariableNameNotUnique);
});
test('Validator should notice invalid macro attribute statement type 1', async () => {
@ -159,7 +159,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
});
test('Validator should notice invalid macro attribute statement type 2', async () => {
@ -185,7 +185,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
});
test('Validator should notice invalid macro attribute statement type 3', async () => {
@ -211,7 +211,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
});
test('Validator should notice invalid macro attribute statement type 4', async () => {
@ -239,7 +239,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAttributeTypeDoesNotMatch);
});
test('Validator should notice macro assignment on attribute variable', async () => {
@ -263,7 +263,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAssignReferenceTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAssignReferenceTypeDoesNotMatch);
});
test('Validator should notice non-matching macro assignment class type', async () => {
@ -289,7 +289,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.MacroAssignReferenceTypeDoesNotMatch);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.MacroAssignReferenceTypeDoesNotMatch);
});
test('Validator should notice instantiation of abstract class', async () => {
@ -307,7 +307,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InstantiationOfAbstractClass);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InstantiationOfAbstractClass);
});
test('Validator should notice instantiation of interface', async () => {
@ -325,8 +325,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfInterface);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfInterface);
});
test('Validator should notice instantiation of primitive type', async () => {
@ -339,8 +339,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfPrimitiveType);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfPrimitiveType);
});
test('Validator should notice instantiation of enum class', async () => {
@ -359,8 +359,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfEnum);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfEnum);
});
test('Validator should notice usage of abstract type', async () => {
@ -378,7 +378,7 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.InstantiationOfAbstractClass);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.InstantiationOfAbstractClass);
});
test('Validator should notice usage of interface', async () => {
@ -396,8 +396,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfInterface);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfInterface);
});
test('Validator should notice usage of primitive type', async () => {
@ -410,8 +410,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfPrimitiveType);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfPrimitiveType);
});
test('Validator should notice usage of enum class', async () => {
@ -430,8 +430,8 @@ describe('Macro validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual("linking-error");
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.InstantiationOfEnum);
expectErrorCode(validationResult, 0).toEqual(undefined);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.InstantiationOfEnum);
});
test('Validator should succeed', async () => {

View file

@ -1,6 +1,6 @@
import {describe, expect, test} from "vitest";
import {getValidation} from "./testutils";
import {IssueCodes} from "../src/language-server/model-modeling-language-validator";
import {expectErrorCode, getValidation} from "./testutils.js";
import {IssueCodes} from "../src/language/model-modeling-language-validator.js";
describe('Package validator tests', () => {
@ -13,7 +13,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.PackageNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.PackageNameNotUnique);
});
test('Validator should notice non-unique sub-package names', async () => {
@ -27,7 +27,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.SubPackageNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.SubPackageNameNotUnique);
});
test('Validator should notice non-unique package and sub-package names', async () => {
@ -43,8 +43,8 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(2);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.PackageNameNotUnique);
expect(validationResult.diagnostics.at(1).code).toEqual(IssueCodes.SubPackageNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.PackageNameNotUnique);
expectErrorCode(validationResult, 1).toEqual(IssueCodes.SubPackageNameNotUnique);
});
test('Validator should notice non-unique element names 1', async () => {
@ -58,7 +58,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names 2', async () => {
@ -72,7 +72,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names 3', async () => {
@ -87,7 +87,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names 4', async () => {
@ -101,7 +101,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names 5', async () => {
@ -116,7 +116,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names 6', async () => {
@ -130,7 +130,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names in subpackage 1', async () => {
@ -146,7 +146,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator should notice non-unique element names in subpackage 2', async () => {
@ -163,7 +163,7 @@ describe('Package validator tests', () => {
`);
expect(validationResult.diagnostics.length).toEqual(1);
expect(validationResult.diagnostics.at(0).code).toEqual(IssueCodes.ElementNameNotUnique);
expectErrorCode(validationResult, 0).toEqual(IssueCodes.ElementNameNotUnique);
});
test('Validator succeed', async () => {

View file

@ -1,15 +1,15 @@
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"lib": ["ESNext","DOM","WebWorker"],
"target": "ES2017",
"module": "Node16",
"lib": ["ESNext"],
"sourceMap": true,
"outDir": "out",
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"noImplicitOverride": true,
"moduleResolution": "node",
"moduleResolution": "Node16",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
@ -19,6 +19,6 @@
],
"exclude": [
"out",
"/node_modules"
"node_modules"
]
}