diff --git a/index.html b/index.html
index 235b5c10e..578d72460 100644
--- a/index.html
+++ b/index.html
@@ -19,7 +19,9 @@
Examples
Please execute npm run start:example:server
beforehand:
Web Client for Node.js Language Server
- Web Client & Langium Web Worker Language Server Example
+ Web Client & Langium LS (Web Worker)
+
+ Web Client & Statemachine LS (Web Worker)
Browser Example
diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json
new file mode 100644
index 000000000..25c9de527
--- /dev/null
+++ b/packages/client/tsconfig.json
@@ -0,0 +1,12 @@
+// this file is required for VSCode to work properly
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "noEmit": true,
+ "rootDir": "."
+ },
+ "include": [
+ "src/**/*",
+ "test/**/*"
+ ]
+}
diff --git a/packages/examples/main/langium_wwls.html b/packages/examples/main/langium_client.html
similarity index 86%
rename from packages/examples/main/langium_wwls.html
rename to packages/examples/main/langium_client.html
index f9e466816..fd945577b 100644
--- a/packages/examples/main/langium_wwls.html
+++ b/packages/examples/main/langium_client.html
@@ -10,7 +10,7 @@
Monaco Language Client & Langium Web Worker Language Server Example
-
+
diff --git a/packages/examples/main/package.json b/packages/examples/main/package.json
index 5d41d9fe7..b5d2ad656 100644
--- a/packages/examples/main/package.json
+++ b/packages/examples/main/package.json
@@ -52,11 +52,11 @@
"clean": "shx rm -fr dist *.tsbuildinfo",
"compile": "tsc --build tsconfig.src.json",
"build:msg": "echo Building main examples:",
- "build:worker:vite": "vite --config vite.langium-worker.ts build",
- "build:worker": "esbuild ../../../node_modules/langium-statemachine-dsl/out/language-server/main-browser.js --bundle --tree-shaking=true --minify --format=iife --outfile=./dist/worker/statemachineServerWorker.js",
- "build": "npm run build:msg && npm run clean && npm run compile && npm run build:worker",
+ "build:worker:vite": "vite --config vite.statemachine-worker.ts build",
+ "build:worker:statemachine": "esbuild ../../../node_modules/langium-statemachine-dsl/out/language-server/main-browser.js --bundle --tree-shaking=true --minify --format=iife --outfile=./dist/worker/statemachineServerWorker.js",
+ "build:worker:langium": "esbuild ./src/langium/langiumServerWorker.js --bundle --tree-shaking=true --minify --format=iife --outfile=./dist/worker/langiumServerWorker.js",
+ "build": "npm run build:msg && npm run clean && npm run compile && npm run build:worker:statemachine && npm run build:worker:langium",
"start": "node --loader ts-node/esm src/server/main.ts",
- "start:ext": "node --loader ts-node/esm src/server/main.ts --external",
- "fetch:themes": "node resources/fetchThemes.mjs"
+ "start:ext": "node --loader ts-node/esm src/server/main.ts --external"
}
}
\ No newline at end of file
diff --git a/packages/examples/main/src/langium/example.langium b/packages/examples/main/src/langium/example.langium
new file mode 100644
index 000000000..fb187aae5
--- /dev/null
+++ b/packages/examples/main/src/langium/example.langium
@@ -0,0 +1,215 @@
+/******************************************************************************
+ * Copyright 2021 TypeFox GmbH
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License, which is available in the project root.
+ ******************************************************************************/
+grammar LangiumGrammar
+
+entry Grammar:
+ (
+ isDeclared?='grammar' name=ID ('with' usedGrammars+=[Grammar:ID] (',' usedGrammars+=[Grammar:ID])*)?
+ (definesHiddenTokens?='hidden' '(' (hiddenTokens+=[AbstractRule:ID] (',' hiddenTokens+=[AbstractRule:ID])*)? ')')?
+ )?
+ imports+=GrammarImport*
+ (rules+=AbstractRule | interfaces+=Interface | types+=Type)+;
+
+Interface:
+ 'interface' name=ID
+ ('extends' superTypes+=[AbstractType:ID] (',' superTypes+=[AbstractType:ID])*)?
+ SchemaType;
+
+fragment SchemaType:
+ '{' attributes+=TypeAttribute* '}' ';'?;
+
+TypeAttribute:
+ name=FeatureName (isOptional?='?')? ':' type=TypeDefinition ';'?;
+
+TypeDefinition: UnionType;
+
+UnionType infers TypeDefinition:
+ ArrayType ({infer UnionType.types+=current} ('|' types+=ArrayType)+)?;
+
+ArrayType infers TypeDefinition:
+ ReferenceType ({infer ArrayType.elementType=current} '[' ']')? ;
+
+ReferenceType infers TypeDefinition:
+ SimpleType |
+ {infer ReferenceType} '@' referenceType=SimpleType;
+
+SimpleType infers TypeDefinition:
+ '(' TypeDefinition ')' |
+ {infer SimpleType} (typeRef=[AbstractType:ID] | primitiveType=PrimitiveType | stringType=STRING);
+
+PrimitiveType returns string:
+ 'string' | 'number' | 'boolean' | 'Date' | 'bigint';
+
+type AbstractType = Interface | Type | Action | ParserRule;
+
+Type:
+ 'type' name=ID '=' type=TypeDefinition ';'?;
+
+AbstractRule:
+ ParserRule | TerminalRule;
+
+GrammarImport:
+ 'import' path=STRING ';'?;
+
+ParserRule:
+ (entry?='entry' | fragment?='fragment')?
+ RuleNameAndParams
+ (wildcard?='*' | ('returns' (returnType=[AbstractType:ID] | dataType=PrimitiveType)) | inferredType=InferredType)?
+ (definesHiddenTokens?='hidden' '(' (hiddenTokens+=[AbstractRule:ID] (',' hiddenTokens+=[AbstractRule:ID])*)? ')')? ':'
+ definition=Alternatives ';';
+
+InferredType:
+ ( 'infer' | 'infers') name=ID;
+
+fragment RuleNameAndParams:
+ name=ID ('<' (parameters+=Parameter (',' parameters+=Parameter)*)? '>')?;
+
+Parameter:
+ name=ID;
+
+Alternatives infers AbstractElement:
+ ConditionalBranch ({infer Alternatives.elements+=current} ('|' elements+=ConditionalBranch)+)?;
+
+ConditionalBranch infers AbstractElement:
+ UnorderedGroup
+ | {infer Group} '<' guardCondition=Disjunction '>' (elements+=AbstractToken)+;
+
+UnorderedGroup infers AbstractElement:
+ Group ({infer UnorderedGroup.elements+=current} ('&' elements+=Group)+)?;
+
+Group infers AbstractElement:
+ AbstractToken ({infer Group.elements+=current} elements+=AbstractToken+)?;
+
+AbstractToken infers AbstractElement:
+ AbstractTokenWithCardinality |
+ Action;
+
+AbstractTokenWithCardinality infers AbstractElement:
+ (Assignment | AbstractTerminal) cardinality=('?'|'*'|'+')?;
+
+Action infers AbstractElement:
+ {infer Action} '{' (type=[AbstractType:ID] | inferredType=InferredType) ('.' feature=FeatureName operator=('='|'+=') 'current')? '}';
+
+AbstractTerminal infers AbstractElement:
+ Keyword |
+ RuleCall |
+ ParenthesizedElement |
+ PredicatedKeyword |
+ PredicatedRuleCall |
+ PredicatedGroup;
+
+Keyword:
+ value=STRING;
+
+RuleCall:
+ rule=[AbstractRule:ID] ('<' arguments+=NamedArgument (',' arguments+=NamedArgument)* '>')?;
+
+NamedArgument:
+ ( parameter=[Parameter:ID] calledByName?='=')?
+ ( value=Disjunction );
+
+LiteralCondition:
+ true?='true' | 'false';
+
+Disjunction infers Condition:
+ Conjunction ({infer Disjunction.left=current} '|' right=Conjunction)*;
+
+Conjunction infers Condition:
+ Negation ({infer Conjunction.left=current} '&' right=Negation)*;
+
+Negation infers Condition:
+ Atom | {infer Negation} '!' value=Negation;
+
+Atom infers Condition:
+ ParameterReference | ParenthesizedCondition | LiteralCondition;
+
+ParenthesizedCondition infers Condition:
+ '(' Disjunction ')';
+
+ParameterReference:
+ parameter=[Parameter:ID];
+
+PredicatedKeyword infers Keyword:
+ ('=>' | '->') value=STRING;
+
+PredicatedRuleCall infers RuleCall:
+ ('=>' | '->') rule=[AbstractRule:ID] ('<' arguments+=NamedArgument (',' arguments+=NamedArgument)* '>')?;
+
+Assignment infers AbstractElement:
+ {infer Assignment} ('=>' | '->')? feature=FeatureName operator=('+='|'='|'?=') terminal=AssignableTerminal;
+
+AssignableTerminal infers AbstractElement:
+ Keyword | RuleCall | ParenthesizedAssignableElement | CrossReference;
+
+ParenthesizedAssignableElement infers AbstractElement:
+ '(' AssignableAlternatives ')';
+
+AssignableAlternatives infers AbstractElement:
+ AssignableTerminal ({infer Alternatives.elements+=current} ('|' elements+=AssignableTerminal)+)?;
+
+CrossReference infers AbstractElement:
+ {infer CrossReference} '[' type=[AbstractType] ((deprecatedSyntax?='|' | ':') terminal=CrossReferenceableTerminal )? ']';
+
+CrossReferenceableTerminal infers AbstractElement:
+ Keyword | RuleCall;
+
+ParenthesizedElement infers AbstractElement:
+ '(' Alternatives ')';
+
+PredicatedGroup infers Group:
+ ('=>' | '->') '(' elements+=Alternatives ')';
+
+ReturnType:
+ name=(PrimitiveType | ID);
+
+TerminalRule:
+ hidden?='hidden'? 'terminal' (fragment?='fragment' name=ID | name=ID ('returns' type=ReturnType)?) ':'
+ definition=TerminalAlternatives
+ ';';
+
+TerminalAlternatives infers AbstractElement:
+ TerminalGroup ({infer TerminalAlternatives.elements+=current} '|' elements+=TerminalGroup)*;
+
+TerminalGroup infers AbstractElement:
+ TerminalToken ({infer TerminalGroup.elements+=current} elements+=TerminalToken+)?;
+
+TerminalToken infers AbstractElement:
+ TerminalTokenElement cardinality=('?'|'*'|'+')?;
+
+TerminalTokenElement infers AbstractElement:
+ CharacterRange | TerminalRuleCall | ParenthesizedTerminalElement | NegatedToken | UntilToken | RegexToken | Wildcard;
+
+ParenthesizedTerminalElement infers AbstractElement:
+ '(' (lookahead=('?='|'?!'))? TerminalAlternatives ')';
+
+TerminalRuleCall infers AbstractElement:
+ {infer TerminalRuleCall} rule=[TerminalRule:ID];
+
+NegatedToken infers AbstractElement:
+ {infer NegatedToken} '!' terminal=TerminalTokenElement;
+
+UntilToken infers AbstractElement:
+ {infer UntilToken} '->' terminal=TerminalTokenElement;
+
+RegexToken infers AbstractElement:
+ {infer RegexToken} regex=RegexLiteral;
+
+Wildcard infers AbstractElement:
+ {infer Wildcard} '.';
+
+CharacterRange infers AbstractElement:
+ {infer CharacterRange} left=Keyword ('..' right=Keyword)?;
+
+FeatureName returns string:
+ 'current' | 'entry' | 'extends' | 'false' | 'fragment' | 'grammar' | 'hidden' | 'import' | 'interface' | 'returns' | 'terminal' | 'true' | 'type' | 'infer' | 'infers' | 'with' | PrimitiveType | ID;
+
+terminal ID: /\^?[_a-zA-Z][\w_]*/;
+terminal STRING: /"(\\.|[^"\\])*"|'(\\.|[^'\\])*'/;
+terminal RegexLiteral returns string: /\/(?![*+?])(?:[^\r\n\[/\\]|\\.|\[(?:[^\r\n\]\\]|\\.)*\])+\//;
+
+hidden terminal WS: /\s+/;
+hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
+hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
diff --git a/packages/examples/main/src/langium/langium.configuration.json b/packages/examples/main/src/langium/langium.configuration.json
new file mode 100644
index 000000000..5b4cc263e
--- /dev/null
+++ b/packages/examples/main/src/langium/langium.configuration.json
@@ -0,0 +1,164 @@
+{
+ "comments": {
+ "lineComment": "//",
+ "blockComment": [
+ "/*",
+ "*/"
+ ]
+ },
+ "brackets": [
+ [
+ "{",
+ "}"
+ ],
+ [
+ "[",
+ "]"
+ ],
+ [
+ "(",
+ ")"
+ ]
+ ],
+ "autoClosingPairs": [
+ {
+ "open": "{",
+ "close": "}"
+ },
+ {
+ "open": "[",
+ "close": "]"
+ },
+ {
+ "open": "(",
+ "close": ")"
+ },
+ {
+ "open": "'",
+ "close": "'",
+ "notIn": [
+ "string",
+ "comment"
+ ]
+ },
+ {
+ "open": "\"",
+ "close": "\"",
+ "notIn": [
+ "string"
+ ]
+ },
+ {
+ "open": "/**",
+ "close": " */",
+ "notIn": [
+ "string"
+ ]
+ }
+ ],
+ "autoCloseBefore": "}])`\n\t",
+ "surroundingPairs": [
+ [
+ "{",
+ "}"
+ ],
+ [
+ "[",
+ "]"
+ ],
+ [
+ "(",
+ ")"
+ ]
+ ],
+ "colorizedBracketPairs": [
+ [
+ "(",
+ ")"
+ ],
+ [
+ "[",
+ "]"
+ ],
+ [
+ "{",
+ "}"
+ ],
+ [
+ "<",
+ ">"
+ ],
+ [
+ "'",
+ "'"
+ ],
+ [
+ "\"",
+ "\""
+ ],
+ [
+ "<",
+ ">"
+ ]
+ ],
+ "onEnterRules": [
+ {
+ "": "// e.g. /** | */",
+ "beforeText": {
+ "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$"
+ },
+ "afterText": {
+ "pattern": "^\\s*\\*/$"
+ },
+ "action": {
+ "indent": "indentOutdent",
+ "appendText": " * "
+ }
+ },
+ {
+ "": "// e.g. /** ...|",
+ "beforeText": {
+ "pattern": "^\\s*/\\*\\*(?!/)([^\\*]|\\*(?!/))*$"
+ },
+ "action": {
+ "indent": "none",
+ "appendText": " * "
+ }
+ },
+ {
+ "": "// e.g. * ...|",
+ "beforeText": {
+ "pattern": "^(\\t|[ ])*[ ]\\*([ ]([^\\*]|\\*(?!/))*)?$"
+ },
+ "previousLineText": {
+ "pattern": "(?=^(\\s*(/\\*\\*|\\*)).*)(?=(?!(\\s*\\*/)))"
+ },
+ "action": {
+ "indent": "none",
+ "appendText": "* "
+ }
+ },
+ {
+ "": "// e.g. */|",
+ "beforeText": {
+ "pattern": "^(\\t|[ ])*[ ]\\*/\\s*$"
+ },
+ "action": {
+ "indent": "none",
+ "removeText": 1
+ }
+ },
+ {
+ "beforeText": ":\\s*$",
+ "action": {
+ "indent": "indent"
+ }
+ },
+ {
+ "beforeText": ";\\s*$",
+ "action": {
+ "indent": "outdent"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/examples/main/src/langium/langium.tmLanguage.json b/packages/examples/main/src/langium/langium.tmLanguage.json
new file mode 100644
index 000000000..468c9f90e
--- /dev/null
+++ b/packages/examples/main/src/langium/langium.tmLanguage.json
@@ -0,0 +1,251 @@
+{
+ "name": "Langium",
+ "scopeName": "source.langium",
+ "fileTypes": [
+ "langium"
+ ],
+ "patterns": [
+ {
+ "include": "#regex"
+ },
+ {
+ "include": "#comments"
+ },
+ {
+ "name": "keyword.control.langium",
+ "match": "\\b(current|entry|extends|fragment|grammar|hidden|import|infer|infers|interface|returns|terminal|type|with)\\b"
+ },
+ {
+ "name": "constant.language.langium",
+ "match": "\\b(?i:true|false)\\b"
+ },
+ {
+ "name": "keyword.symbol.langium",
+ "match": "(\\{|\\}|\\:|\\]|\\[|\\(|\\)|(\\??|\\+?)\\=|->|\\=>|<|>|\\,|\\*|\\+|\\@|\\||\\&|\\?|\\!|\\;)"
+ },
+ {
+ "name": "string.quoted.double.langium",
+ "begin": "\"",
+ "end": "\"",
+ "patterns": [
+ {
+ "include": "#string-character-escape"
+ }
+ ]
+ },
+ {
+ "name": "string.quoted.single.langium",
+ "begin": "'",
+ "end": "'",
+ "patterns": [
+ {
+ "include": "#string-character-escape"
+ }
+ ]
+ }
+ ],
+ "repository": {
+ "comments": {
+ "patterns": [
+ {
+ "name": "comment.block.langium",
+ "begin": "/\\*",
+ "beginCaptures": {
+ "0": {
+ "name": "punctuation.definition.comment.langium"
+ }
+ },
+ "end": "\\*/",
+ "endCaptures": {
+ "0": {
+ "name": "punctuation.definition.comment.langium"
+ }
+ }
+ },
+ {
+ "begin": "(^\\s+)?(?=//)",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.whitespace.comment.leading.cs"
+ }
+ },
+ "end": "(?=$)",
+ "name": "comment.line.langium"
+ }
+ ]
+ },
+ "string-character-escape": {
+ "name": "constant.character.escape.langium",
+ "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]?|.|$)"
+ },
+ "regex": {
+ "patterns": [
+ {
+ "name": "string.regex.langium",
+ "begin": "/(?![/*])(?=(?:[^/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+/(?![/*]))",
+ "beginCaptures": {
+ "0": {
+ "name": "punctuation.definition.string.begin.langium"
+ }
+ },
+ "end": "/",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.string.end.langium"
+ },
+ "2": {
+ "name": "keyword.other.langium"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#regexp"
+ }
+ ]
+ }
+ ]
+ },
+ "regexp": {
+ "patterns": [
+ {
+ "name": "keyword.control.anchor.regexp",
+ "match": "\\\\[bB]|\\^|\\$"
+ },
+ {
+ "name": "keyword.other.back-reference.regexp",
+ "match": "\\\\[1-9]\\d*"
+ },
+ {
+ "name": "keyword.operator.quantifier.regexp",
+ "match": "[?+*]|\\{(\\d+,\\d+|\\d+,|,\\d+|\\d+)\\}\\??"
+ },
+ {
+ "name": "keyword.operator.or.regexp",
+ "match": "\\|"
+ },
+ {
+ "name": "meta.group.assertion.regexp",
+ "begin": "(\\()((\\?=)|(\\?!))",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.group.regexp"
+ },
+ "2": {
+ "name": "punctuation.definition.group.assertion.regexp"
+ },
+ "3": {
+ "name": "meta.assertion.look-ahead.regexp"
+ },
+ "4": {
+ "name": "meta.assertion.negative-look-ahead.regexp"
+ }
+ },
+ "end": "(\\))",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.group.regexp"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#regexp"
+ }
+ ]
+ },
+ {
+ "name": "meta.group.regexp",
+ "begin": "\\((\\?:)?",
+ "beginCaptures": {
+ "0": {
+ "name": "punctuation.definition.group.regexp"
+ },
+ "1": {
+ "name": "punctuation.definition.group.capture.regexp"
+ }
+ },
+ "end": "\\)",
+ "endCaptures": {
+ "0": {
+ "name": "punctuation.definition.group.regexp"
+ }
+ },
+ "patterns": [
+ {
+ "include": "#regexp"
+ }
+ ]
+ },
+ {
+ "name": "constant.other.character-class.set.regexp",
+ "begin": "(\\[)(\\^)?",
+ "beginCaptures": {
+ "1": {
+ "name": "punctuation.definition.character-class.regexp"
+ },
+ "2": {
+ "name": "keyword.operator.negation.regexp"
+ }
+ },
+ "end": "(\\])",
+ "endCaptures": {
+ "1": {
+ "name": "punctuation.definition.character-class.regexp"
+ }
+ },
+ "patterns": [
+ {
+ "name": "constant.other.character-class.range.regexp",
+ "match": "(?:.|(\\\\(?:[0-7]{3}|x\\h\\h|u\\h\\h\\h\\h))|(\\\\c[A-Z])|(\\\\.))\\-(?:[^\\]\\\\]|(\\\\(?:[0-7]{3}|x\\h\\h|u\\h\\h\\h\\h))|(\\\\c[A-Z])|(\\\\.))",
+ "captures": {
+ "1": {
+ "name": "constant.character.numeric.regexp"
+ },
+ "2": {
+ "name": "constant.character.control.regexp"
+ },
+ "3": {
+ "name": "constant.character.escape.backslash.regexp"
+ },
+ "4": {
+ "name": "constant.character.numeric.regexp"
+ },
+ "5": {
+ "name": "constant.character.control.regexp"
+ },
+ "6": {
+ "name": "constant.character.escape.backslash.regexp"
+ }
+ }
+ },
+ {
+ "include": "#regex-character-class"
+ }
+ ]
+ },
+ {
+ "include": "#regex-character-class"
+ }
+ ]
+ },
+ "regex-character-class": {
+ "patterns": [
+ {
+ "name": "constant.other.character-class.regexp",
+ "match": "\\\\[wWsSdDtrnvf]|\\."
+ },
+ {
+ "name": "constant.character.numeric.regexp",
+ "match": "\\\\([0-7]{3}|x\\h\\h|u\\h\\h\\h\\h)"
+ },
+ {
+ "name": "constant.character.control.regexp",
+ "match": "\\\\c[A-Z]"
+ },
+ {
+ "name": "constant.character.escape.backslash.regexp",
+ "match": "\\\\."
+ }
+ ]
+ }
+ }
+}
diff --git a/packages/examples/main/src/langium/langiumClient.ts b/packages/examples/main/src/langium/langiumClient.ts
new file mode 100644
index 000000000..dd47211fb
--- /dev/null
+++ b/packages/examples/main/src/langium/langiumClient.ts
@@ -0,0 +1,151 @@
+/* --------------------------------------------------------------------------------------------
+ * Copyright (c) 2018-2022 TypeFox GmbH (http://www.typefox.io). All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ * ------------------------------------------------------------------------------------------ */
+
+import 'monaco-editor/esm/vs/editor/editor.all.js';
+import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js';
+import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js';
+import { editor, Uri } from 'monaco-editor/esm/vs/editor/editor.api.js';
+
+import { MonacoLanguageClient, initServices } from 'monaco-languageclient';
+import { BrowserMessageReader, BrowserMessageWriter } from 'vscode-languageserver-protocol/browser.js';
+import { CloseAction, ErrorAction, MessageTransports } from 'vscode-languageclient';
+
+import { createConfiguredEditor } from 'vscode/monaco';
+import { registerExtension } from 'vscode/extensions';
+import { updateUserConfiguration } from 'vscode/service-override/configuration';
+import 'vscode/default-extensions/theme-defaults';
+
+import { buildWorkerDefinition } from 'monaco-editor-workers';
+buildWorkerDefinition('../../../node_modules/monaco-editor-workers/dist/workers/', new URL('', window.location.href).href, false);
+
+const languageId = 'langium';
+
+const setup = async () => {
+ console.log('Setting up Langium configuration ...');
+ const extension = {
+ name: 'langium-example',
+ publisher: 'monaco-languageclient-project',
+ version: '1.0.0',
+ engines: {
+ vscode: '*'
+ },
+ contributes: {
+ languages: [{
+ id: languageId,
+ extensions: [
+ `.${languageId}`
+ ],
+ aliases: [
+ languageId
+ ],
+ configuration: './langium-configuration.json'
+ }],
+ grammars: [{
+ language: languageId,
+ scopeName: 'source.langium',
+ path: './langium-grammar.json'
+ }],
+ keybindings: [{
+ key: 'ctrl+p',
+ command: 'editor.action.quickCommand',
+ when: 'editorTextFocus'
+ }, {
+ key: 'ctrl+shift+c',
+ command: 'editor.action.commentLine',
+ when: 'editorTextFocus'
+ }]
+ }
+ };
+ const { registerFile: registerExtensionFile } = registerExtension(extension);
+
+ registerExtensionFile('/langium-configuration.json', async () => {
+ const langiumLanguageConfig = new URL('./src/langium/langium.configuration.json', window.location.href).href;
+ return (await fetch(langiumLanguageConfig)).text();
+ });
+
+ registerExtensionFile('/langium-grammar.json', async () => {
+ const langiumTmUrl = new URL('./src/langium/langium.tmLanguage.json', window.location.href).href;
+ return (await fetch(langiumTmUrl)).text();
+ });
+
+ updateUserConfiguration(`{
+ "workbench.colorTheme": "Default Dark Modern"
+}`);
+};
+
+const run = async () => {
+ const exampleLangiumUrl = new URL('./src/langium/example.langium', window.location.href).href;
+ const responseLangium = await fetch(exampleLangiumUrl);
+ const editorText = await responseLangium.text();
+
+ const editorOptions = {
+ model: editor.createModel(editorText, languageId, Uri.parse('inmemory://example.langium')),
+ automaticLayout: true
+ };
+ createConfiguredEditor(document.getElementById('container')!, editorOptions);
+
+ function createLanguageClient(transports: MessageTransports): MonacoLanguageClient {
+ return new MonacoLanguageClient({
+ name: 'Langium Client',
+ clientOptions: {
+ // use a language id as a document selector
+ documentSelector: [{ language: languageId }],
+ // disable the default error handler
+ errorHandler: {
+ error: () => ({ action: ErrorAction.Continue }),
+ closed: () => ({ action: CloseAction.DoNotRestart })
+ }
+ },
+ // create a language client connection to the server running in the web worker
+ connectionProvider: {
+ get: () => {
+ return Promise.resolve(transports);
+ }
+ }
+ });
+ }
+
+ const langiumWorkerUrl = new URL('./src/langium/langiumServerWorker.ts', window.location.href).href;
+ const worker = new Worker(langiumWorkerUrl, {
+ type: 'module',
+ name: 'Langium LS'
+ });
+ const reader = new BrowserMessageReader(worker);
+ const writer = new BrowserMessageWriter(worker);
+ const languageClient = createLanguageClient({ reader, writer });
+ languageClient.start();
+ reader.onClose(() => languageClient.stop());
+
+ languageClient.onTelemetry((t) => {
+ console.log(t);
+ });
+
+ languageClient.sendNotification('tester', { test: 'test' });
+
+ // any further language client / server interaction can't be defined as needed
+};
+
+try {
+ await initServices({
+ enableFilesService: true,
+ enableThemeService: true,
+ enableTextmateService: true,
+ enableModelService: true,
+ configureEditorOrViewsServiceConfig: {
+ enableViewsService: false,
+ useDefaultOpenEditorFunction: true
+ },
+ configureConfigurationServiceConfig: {
+ defaultWorkspaceUri: '/tmp'
+ },
+ enableKeybindingsService: true,
+ enableLanguagesService: true,
+ debugLogging: true
+ });
+ await setup();
+ await run();
+} catch (e) {
+ console.log(e);
+}
diff --git a/packages/examples/main/src/langium/langiumServerWorker.ts b/packages/examples/main/src/langium/langiumServerWorker.ts
new file mode 100644
index 000000000..96aeefdce
--- /dev/null
+++ b/packages/examples/main/src/langium/langiumServerWorker.ts
@@ -0,0 +1,21 @@
+/* --------------------------------------------------------------------------------------------
+ * Copyright (c) 2018-2022 TypeFox GmbH (http://www.typefox.io). All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ * ------------------------------------------------------------------------------------------ */
+
+import { createLangiumGrammarServices, startLanguageServer, EmptyFileSystem, DefaultSharedModuleContext } from 'langium';
+import { BrowserMessageReader, BrowserMessageWriter, createConnection } from 'vscode-languageserver/browser.js';
+
+/* browser specific setup code */
+const messageReader = new BrowserMessageReader(self as DedicatedWorkerGlobalScope);
+const messageWriter = new BrowserMessageWriter(self as DedicatedWorkerGlobalScope);
+
+// Inject the shared services and language-specific services
+const context = {
+ connection: createConnection(messageReader, messageWriter),
+ ...EmptyFileSystem
+} as unknown as DefaultSharedModuleContext;
+const { shared } = createLangiumGrammarServices(context);
+
+// Start the language server with the shared services
+startLanguageServer(shared);
diff --git a/packages/examples/main/src/langium/main.ts b/packages/examples/main/src/langium/statemachineClient.ts
similarity index 100%
rename from packages/examples/main/src/langium/main.ts
rename to packages/examples/main/src/langium/statemachineClient.ts
diff --git a/packages/examples/main/statemachine_client.html b/packages/examples/main/statemachine_client.html
new file mode 100644
index 000000000..36dea61fd
--- /dev/null
+++ b/packages/examples/main/statemachine_client.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Monaco Language Client & Langium Web Worker Language Server Example
+
+
+
+
+
+ Monaco Language Client & Langium Web Worker Language Server Example
+
+
+
+
+
+
diff --git a/packages/examples/main/tsconfig.json b/packages/examples/main/tsconfig.json
new file mode 100644
index 000000000..25c9de527
--- /dev/null
+++ b/packages/examples/main/tsconfig.json
@@ -0,0 +1,12 @@
+// this file is required for VSCode to work properly
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "noEmit": true,
+ "rootDir": "."
+ },
+ "include": [
+ "src/**/*",
+ "test/**/*"
+ ]
+}
diff --git a/packages/examples/main/tsconfig.src.json b/packages/examples/main/tsconfig.src.json
index 6acbf70a1..ced2f27a3 100644
--- a/packages/examples/main/tsconfig.src.json
+++ b/packages/examples/main/tsconfig.src.json
@@ -12,7 +12,10 @@
"node"
],
"references": [{
- "path": "../../client/tsconfig.src.json"
+ "path": "../../client/tsconfig.src.json",
+ },
+ {
+ "path": "../../vscode-ws-jsonrpc/tsconfig.src.json"
}],
"include": [
"src/**/*.ts",
diff --git a/packages/examples/main/vite.langium-worker.ts b/packages/examples/main/vite.statemachine-worker.ts
similarity index 100%
rename from packages/examples/main/vite.langium-worker.ts
rename to packages/examples/main/vite.statemachine-worker.ts
diff --git a/packages/vscode-ws-jsonrpc/tsconfig.json b/packages/vscode-ws-jsonrpc/tsconfig.json
new file mode 100644
index 000000000..25c9de527
--- /dev/null
+++ b/packages/vscode-ws-jsonrpc/tsconfig.json
@@ -0,0 +1,12 @@
+// this file is required for VSCode to work properly
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "noEmit": true,
+ "rootDir": "."
+ },
+ "include": [
+ "src/**/*",
+ "test/**/*"
+ ]
+}
diff --git a/vite.config.ts b/vite.config.ts
index 7176c406c..193a385ad 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -8,7 +8,8 @@ export default defineConfig(() => {
rollupOptions: {
input: {
client: resolve(__dirname, 'packages/examples/main/client.html'),
- langiumLsp: resolve(__dirname, 'packages/examples/main/langium_wwls.html'),
+ langiumClient: resolve(__dirname, 'packages/examples/main/langium_client.html'),
+ statemachineClient: resolve(__dirname, 'packages/examples/main/statemachine_client.html'),
browser: resolve(__dirname, 'packages/examples/main/browser.html'),
react: resolve(__dirname, 'packages/examples/main/react.html')
}