@likec4/language-server 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { createLanguageServices } from './module';
2
+ export type { LikeC4Services } from './module';
2
3
  export { LikeC4LanguageMetaData as LanguageMetaData } from './generated/module';
3
4
  export { Rpc } from './protocol';
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // import { type DefaultSharedModuleContext, startLanguageServer as startLangiumLanguageServer } from 'langium'
2
2
  export { createLanguageServices } from './module';
3
- // export type { C4XServices }
4
3
  // export type { C4XModel } from './c4x-model'
5
4
  // export type { C4XLangiumDocument } from './ast'
6
5
  // export {
@@ -56,13 +56,15 @@ export class LikeC4DocumentSymbolProvider {
56
56
  }
57
57
  if (specSymbols.length === 0)
58
58
  return [];
59
- return [{
59
+ return [
60
+ {
60
61
  kind: SymbolKind.Class,
61
62
  name: astSpec.name,
62
63
  range: cstModel.range,
63
64
  selectionRange: specKeywordNode.range,
64
65
  children: specSymbols
65
- }];
66
+ }
67
+ ];
66
68
  };
67
69
  getModelSymbols = (astModel) => {
68
70
  const cstModel = astModel?.$cstNode;
@@ -71,13 +73,15 @@ export class LikeC4DocumentSymbolProvider {
71
73
  const nameNode = findNodeForProperty(cstModel, 'name');
72
74
  if (!nameNode)
73
75
  return [];
74
- return [{
76
+ return [
77
+ {
75
78
  kind: SymbolKind.Class,
76
79
  name: astModel.name,
77
80
  range: cstModel.range,
78
81
  selectionRange: nameNode.range,
79
82
  children: astModel.elements.flatMap(this.getElementsSymbol)
80
- }];
83
+ }
84
+ ];
81
85
  };
82
86
  getElementsSymbol = (el) => {
83
87
  if (ast.isExtendElement(el)) {
@@ -93,13 +97,15 @@ export class LikeC4DocumentSymbolProvider {
93
97
  const nameNode = astElement.element.$cstNode;
94
98
  if (!cst || !nameNode)
95
99
  return [];
96
- return [{
100
+ return [
101
+ {
97
102
  kind: SymbolKind.Constructor,
98
103
  name: nameNode.text,
99
104
  range: cst.range,
100
105
  selectionRange: nameNode.range,
101
106
  children: astElement.body.elements.flatMap(this.getElementsSymbol)
102
- }];
107
+ }
108
+ ];
103
109
  };
104
110
  getElementSymbol = (astElement) => {
105
111
  const cst = astElement.$cstNode;
@@ -112,14 +118,16 @@ export class LikeC4DocumentSymbolProvider {
112
118
  const kind = astElement.kind.$refText;
113
119
  // TODO: return the title as well
114
120
  const detail = kind; // + (astElement.title ? ': ' + astElement.title : '').replaceAll('\n', ' ').trim()
115
- return [{
121
+ return [
122
+ {
116
123
  kind: SymbolKind.Constructor,
117
124
  name: name,
118
125
  range: cst.range,
119
126
  selectionRange: nameNode.range,
120
127
  detail,
121
128
  children: astElement.body?.elements.flatMap(this.getElementsSymbol) ?? []
122
- }];
129
+ }
130
+ ];
123
131
  };
124
132
  getModelViewsSymbols = (astViews) => {
125
133
  const cst = astViews?.$cstNode;
@@ -128,12 +136,14 @@ export class LikeC4DocumentSymbolProvider {
128
136
  const nameNode = findNodeForProperty(cst, 'name');
129
137
  if (!nameNode)
130
138
  return [];
131
- return [{
139
+ return [
140
+ {
132
141
  kind: SymbolKind.Class,
133
142
  name: astViews.name,
134
143
  range: cst.range,
135
144
  selectionRange: nameNode.range,
136
145
  children: []
137
- }];
146
+ }
147
+ ];
138
148
  };
139
149
  }
@@ -35,10 +35,7 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
35
35
  if (!el) {
36
36
  return;
37
37
  }
38
- const lines = [
39
- el.id,
40
- `${el.kind}: **${el.title}**`
41
- ];
38
+ const lines = [el.id, `${el.kind}: **${el.title}**`];
42
39
  if (el.tags && el.tags.length > 0) {
43
40
  lines.push(' \n', el.tags.map(t => '#' + t).join(', '));
44
41
  }
@@ -7,25 +7,16 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
7
7
  const keyword = (keyword, _index) => acceptor({
8
8
  node,
9
9
  keyword,
10
- type: SemanticTokenTypes.keyword,
10
+ type: SemanticTokenTypes.keyword
11
11
  });
12
12
  if (ast.isElementRef(node) || ast.isStrictElementRef(node)) {
13
13
  acceptor({
14
14
  node,
15
15
  property: 'el',
16
- type: isElementRefHead(node) ? SemanticTokenTypes.variable : SemanticTokenTypes.property,
16
+ type: isElementRefHead(node) ? SemanticTokenTypes.variable : SemanticTokenTypes.property
17
17
  });
18
- // acceptor({
19
- // node,
20
- // property: 'el',
21
- // type: SemanticTokenTypes.variable,
22
- // })
23
18
  return;
24
19
  }
25
- // if (ast.isSpec(node)) {
26
- // keyword('spec')
27
- // return
28
- // }
29
20
  if (ast.isWildcardExpression(node)) {
30
21
  acceptor({
31
22
  node,
@@ -34,7 +25,9 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
34
25
  });
35
26
  return;
36
27
  }
37
- if (ast.isRelationExpression(node) || ast.isIncomingExpression(node) || ast.isOutgoingExpression(node)) {
28
+ if (ast.isRelationExpression(node) ||
29
+ ast.isIncomingExpression(node) ||
30
+ ast.isOutgoingExpression(node)) {
38
31
  keyword('->');
39
32
  return;
40
33
  }
@@ -54,29 +47,12 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
54
47
  }
55
48
  return;
56
49
  }
57
- // if (ast.isDynamicViewStep(node)) {
58
- // keyword(node.isReverse ? '<-' : '->')
59
- // if (hasTitle(node)) {
60
- // acceptor({
61
- // node,
62
- // property: 'title',
63
- // type: SemanticTokenTypes.string
64
- // })
65
- // }
66
- // return
67
- // }
68
- // if (ast.isStyleProperties(node)) {
69
- // keyword('style')
70
- // return
71
- // }
72
50
  if (ast.isElementKind(node)) {
73
51
  acceptor({
74
52
  node,
75
53
  property: 'name',
76
54
  type: SemanticTokenTypes.type,
77
- modifier: [
78
- SemanticTokenModifiers.definition,
79
- ]
55
+ modifier: [SemanticTokenModifiers.definition]
80
56
  });
81
57
  return;
82
58
  }
@@ -122,11 +98,11 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
122
98
  });
123
99
  return;
124
100
  }
125
- if (ast.isColorProperty(node) || ast.isShapeProperty(node)) {
101
+ if (ast.isAStyleProperty(node)) {
126
102
  acceptor({
127
103
  node,
128
104
  property: 'key',
129
- type: SemanticTokenTypes.keyword,
105
+ type: SemanticTokenTypes.keyword
130
106
  });
131
107
  acceptor({
132
108
  node,
@@ -135,36 +111,34 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
135
111
  });
136
112
  return;
137
113
  }
138
- if (ast.isElementProperty(node) || ast.isRelationProperty(node) || ast.isViewProperty(node)) {
114
+ if (ast.isAnyStringProperty(node)) {
139
115
  acceptor({
140
116
  node,
141
117
  property: 'key',
142
- type: SemanticTokenTypes.keyword,
118
+ type: SemanticTokenTypes.keyword
119
+ });
120
+ acceptor({
121
+ node,
122
+ property: 'value',
123
+ type: SemanticTokenTypes.string
143
124
  });
144
- if ('value' in node) {
145
- acceptor({
146
- node,
147
- property: 'value',
148
- type: SemanticTokenTypes.string
149
- });
150
- }
151
- return;
152
- }
153
- if (ast.isModel(node)) {
154
- keyword('model');
155
- return;
156
- }
157
- if (ast.isModelViews(node)) {
158
- keyword('views');
159
125
  return;
160
126
  }
127
+ // if (ast.isModel(node)) {
128
+ // keyword('model')
129
+ // return
130
+ // }
131
+ // if (ast.isModelViews(node)) {
132
+ // keyword('views')
133
+ // return
134
+ // }
161
135
  if (ast.isElement(node)) {
162
136
  return this.highlightAstElement(node, acceptor);
163
137
  }
164
- if (ast.isExtendElement(node)) {
165
- keyword('extend');
166
- return;
167
- }
138
+ // if (ast.isExtendElement(node)) {
139
+ // keyword('extend')
140
+ // return
141
+ // }
168
142
  // if (ast.isElementProperty(node) || ast.isRelationProperty(node) || ast.isViewProperty(node)) {
169
143
  // acceptor({
170
144
  // node,
@@ -188,28 +162,26 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
188
162
  // keyword('steps')
189
163
  // return
190
164
  // }
191
- if (ast.isViewRuleAutoLayout(node)) {
192
- keyword('autoLayout');
193
- return;
194
- }
195
- if (ast.isViewRuleStyle(node)) {
196
- keyword('style');
197
- return;
198
- }
199
- if (ast.isViewRuleExpression(node)) {
200
- keyword(node.isInclude ? 'include' : 'exclude');
201
- return;
202
- }
203
- //
165
+ // if (ast.isViewRuleAutoLayout(node)) {
166
+ // keyword('autoLayout')
167
+ // return
168
+ // }
169
+ // if (ast.isViewRuleStyle(node)) {
170
+ // keyword('style')
171
+ // return
172
+ // }
173
+ // if (ast.isViewRuleExpression(node)) {
174
+ // keyword(node.isInclude ? 'include' : 'exclude')
175
+ // return
176
+ // }
177
+ // //
204
178
  }
205
179
  highlightAstElement(node, acceptor) {
206
180
  acceptor({
207
181
  node,
208
182
  property: 'name',
209
183
  type: SemanticTokenTypes.variable,
210
- modifier: [
211
- SemanticTokenModifiers.declaration,
212
- ]
184
+ modifier: [SemanticTokenModifiers.declaration]
213
185
  });
214
186
  acceptor({
215
187
  node,
@@ -230,7 +202,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
230
202
  acceptor({
231
203
  node,
232
204
  property: 'name',
233
- type: SemanticTokenTypes.variable,
205
+ type: SemanticTokenTypes.variable
234
206
  });
235
207
  }
236
208
  if (node.viewOf) {
@@ -1,4 +1,3 @@
1
- export * from './CodeLensProvider';
2
1
  export * from './DocumentSymbolProvider';
3
2
  export * from './HoverProvider';
4
3
  export * from './SemanticTokenProvider';
package/dist/lsp/index.js CHANGED
@@ -1,4 +1,3 @@
1
- export * from './CodeLensProvider';
2
1
  export * from './DocumentSymbolProvider';
3
2
  export * from './HoverProvider';
4
3
  export * from './SemanticTokenProvider';
@@ -42,7 +42,7 @@ export class FqnIndex {
42
42
  directChildrenOf(parent) {
43
43
  return this.#index
44
44
  .entriesGroupedByKey()
45
- .flatMap(([fqn, descrs]) => (descrs.length === 1 && parentFqn(fqn) === parent) ? descrs : []);
45
+ .flatMap(([fqn, descrs]) => (descrs.length === 1 && parentFqn(fqn) === parent ? descrs : []));
46
46
  }
47
47
  uniqueDescedants(parent) {
48
48
  return new StreamImpl(() => {
@@ -61,7 +61,7 @@ export class FqnIndex {
61
61
  }
62
62
  }
63
63
  });
64
- if ((children.length + descedants.length) === 0) {
64
+ if (children.length + descedants.length === 0) {
65
65
  return null;
66
66
  }
67
67
  const nested = new MultiMap(children.map(([_fqn, desc]) => [desc.name, desc]));
@@ -72,9 +72,9 @@ export class FqnIndex {
72
72
  }
73
73
  return nested
74
74
  .entriesGroupedByKey()
75
- .flatMap(([_name, descrs]) => descrs.length === 1 ? descrs : [])
75
+ .flatMap(([_name, descrs]) => (descrs.length === 1 ? descrs : []))
76
76
  .iterator();
77
- }, (iterator) => {
77
+ }, iterator => {
78
78
  if (iterator) {
79
79
  return iterator.next();
80
80
  }
@@ -128,7 +128,9 @@ export class FqnIndex {
128
128
  }
129
129
  cleanIndexedElements(docUri) {
130
130
  const docUriAsString = docUri.toString();
131
- const toDelete = this.#index.entries().filter(([, indexed]) => indexed.documentUri.toString() === docUriAsString);
131
+ const toDelete = this.#index
132
+ .entries()
133
+ .filter(([, indexed]) => indexed.documentUri.toString() === docUriAsString);
132
134
  for (const [fqn, indexed] of toDelete.toArray()) {
133
135
  this.#index.delete(fqn, indexed);
134
136
  }
@@ -6,6 +6,7 @@ import { DocumentState, getDocument, interruptAndCheck } from 'langium';
6
6
  import objectHash from 'object-hash';
7
7
  import { clone, isNil, mergeDeepRight, omit, reduce } from 'rambdax';
8
8
  import invariant from 'tiny-invariant';
9
+ import { toAutoLayout } from '../ast';
9
10
  import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toElementStyle } from '../ast';
10
11
  import { elementRef, strictElementRefFqn } from '../elementRef';
11
12
  import { logger } from '../logger';
@@ -67,7 +68,7 @@ export class LikeC4ModelBuilder {
67
68
  return {
68
69
  ...(kind.shape !== DefaultElementShape ? { shape: kind.shape } : {}),
69
70
  ...(kind.color !== DefaultThemeColor ? { color: kind.color } : {}),
70
- ...(omit(['astPath'], el))
71
+ ...omit(['astPath'], el)
71
72
  };
72
73
  }
73
74
  return null;
@@ -127,7 +128,7 @@ export class LikeC4ModelBuilder {
127
128
  const styleProps = toElementStyle(style?.props);
128
129
  specification.kinds[kind.name] = {
129
130
  color: styleProps.color ?? DefaultThemeColor,
130
- shape: styleProps.shape ?? DefaultElementShape,
131
+ shape: styleProps.shape ?? DefaultElementShape
131
132
  };
132
133
  }
133
134
  catch (e) {
@@ -181,7 +182,7 @@ export class LikeC4ModelBuilder {
181
182
  const styleProps = astNode.body?.props.find(ast.isElementStyleProperty)?.props;
182
183
  const { color, shape } = toElementStyle(styleProps);
183
184
  const astPath = this.getAstNodePath(astNode);
184
- let [title, description, technology,] = astNode.props;
185
+ let [title, description, technology] = astNode.props;
185
186
  const bodyProps = astNode.body?.props.filter((p) => ast.isElementStringProperty(p)) ?? [];
186
187
  title = title ?? bodyProps.find(p => p.key === 'title')?.value;
187
188
  description = description ?? bodyProps.find(p => p.key === 'description')?.value;
@@ -195,7 +196,7 @@ export class LikeC4ModelBuilder {
195
196
  ...(description && { description }),
196
197
  ...(tags.length > 0 ? { tags } : {}),
197
198
  ...(shape && shape !== DefaultElementShape ? { shape } : {}),
198
- ...(color && color !== DefaultThemeColor ? { color } : {}),
199
+ ...(color && color !== DefaultThemeColor ? { color } : {})
199
200
  };
200
201
  }
201
202
  parseRelation(astNode) {
@@ -208,11 +209,11 @@ export class LikeC4ModelBuilder {
208
209
  target
209
210
  };
210
211
  const id = objectHash(hashdata);
211
- const title = astNode.definition?.props.find(p => p.key === 'title')?.value ?? '';
212
+ const title = astNode.title ?? astNode.definition?.props.find(p => p.key === 'title')?.value ?? '';
212
213
  return {
213
214
  id,
214
215
  ...hashdata,
215
- title: astNode.title ?? title
216
+ title
216
217
  };
217
218
  }
218
219
  parseElementExpression(astNode) {
@@ -253,7 +254,7 @@ export class LikeC4ModelBuilder {
253
254
  if (ast.isRelationExpression(astNode)) {
254
255
  return {
255
256
  source: this.parseElementExpression(astNode.source),
256
- target: this.parseElementExpression(astNode.target),
257
+ target: this.parseElementExpression(astNode.target)
257
258
  };
258
259
  }
259
260
  failExpectedNever(astNode);
@@ -277,7 +278,7 @@ export class LikeC4ModelBuilder {
277
278
  }
278
279
  if (ast.isViewRuleAutoLayout(astNode)) {
279
280
  return {
280
- autoLayout: astNode.direction
281
+ autoLayout: toAutoLayout(astNode.direction)
281
282
  };
282
283
  }
283
284
  failExpectedNever(astNode);
package/dist/module.js CHANGED
@@ -1,10 +1,11 @@
1
- import { createDefaultModule, inject, createDefaultSharedModule } from 'langium';
1
+ import { createDefaultModule, createDefaultSharedModule, inject } from 'langium';
2
2
  import { LikeC4GeneratedModule, LikeC4GeneratedSharedModule } from './generated/module';
3
- import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
3
+ import { LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
4
4
  import { FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator } from './model';
5
- import { registerValidationChecks } from './validation';
6
- import { LikeC4CodeLensProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
5
+ import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
7
6
  import { registerProtocolHandlers } from './registerProtocolHandlers';
7
+ import { LikeC4CodeLensProvider, LikeC4WorkspaceManager } from './shared';
8
+ import { registerValidationChecks } from './validation';
8
9
  function bind(Type) {
9
10
  return (services) => new Type(services);
10
11
  }
@@ -12,7 +13,7 @@ export const LikeC4Module = {
12
13
  likec4: {
13
14
  FqnIndex: bind(FqnIndex),
14
15
  ModelBuilder: bind(LikeC4ModelBuilder),
15
- ModelLocator: bind(LikeC4ModelLocator),
16
+ ModelLocator: bind(LikeC4ModelLocator)
16
17
  // Model: bind(LikeC4Model),
17
18
  // Model: bind(LikeC4Model),
18
19
  // SpecIndex: bind(LikeC4SpecIndex),
@@ -21,7 +22,7 @@ export const LikeC4Module = {
21
22
  lsp: {
22
23
  DocumentSymbolProvider: bind(LikeC4DocumentSymbolProvider),
23
24
  SemanticTokenProvider: bind(LikeC4SemanticTokenProvider),
24
- HoverProvider: bind(LikeC4HoverProvider),
25
+ HoverProvider: bind(LikeC4HoverProvider)
25
26
  },
26
27
  //
27
28
  // // Formatter: bind(LikeC4Formatter),
@@ -34,8 +35,11 @@ export const LikeC4Module = {
34
35
  };
35
36
  const LikeC4SharedModule = {
36
37
  ...LikeC4GeneratedSharedModule,
38
+ workspace: {
39
+ WorkspaceManager: services => new LikeC4WorkspaceManager(services)
40
+ },
37
41
  lsp: {
38
- CodeLensProvider: (services) => new LikeC4CodeLensProvider(services)
42
+ CodeLensProvider: services => new LikeC4CodeLensProvider(services)
39
43
  }
40
44
  };
41
45
  export function createLanguageServices(context) {
@@ -9,7 +9,7 @@ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
9
9
  getScope(context: ReferenceInfo): Scope;
10
10
  protected computeScope(node: AstNode, referenceType: string): Scope;
11
11
  /**
12
- * Create a global scope filtered for the given reference type.
13
- */
12
+ * Create a global scope filtered for the given reference type.
13
+ */
14
14
  protected getGlobalScope(referenceType: string): Scope;
15
15
  }
@@ -19,7 +19,7 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
19
19
  return this.fqnIndex.uniqueDescedants(fqn).iterator();
20
20
  }
21
21
  return null;
22
- }, (iterator) => {
22
+ }, iterator => {
23
23
  if (iterator) {
24
24
  return iterator.next();
25
25
  }
@@ -37,7 +37,7 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
37
37
  return this.fqnIndex.uniqueDescedants(fqn).iterator();
38
38
  }
39
39
  return null;
40
- }, (iterator) => {
40
+ }, iterator => {
41
41
  if (iterator) {
42
42
  return iterator.next();
43
43
  }
@@ -102,8 +102,8 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
102
102
  }, this.getGlobalScope(referenceType));
103
103
  }
104
104
  /**
105
- * Create a global scope filtered for the given reference type.
106
- */
105
+ * Create a global scope filtered for the given reference type.
106
+ */
107
107
  getGlobalScope(referenceType) {
108
108
  return new StreamScope(this.indexManager.allElements(referenceType));
109
109
  }
@@ -9,7 +9,7 @@ export class LikeC4CodeLensProvider {
9
9
  if (!isParsedLikeC4LangiumDocument(doc)) {
10
10
  return;
11
11
  }
12
- return doc.parseResult.value.views?.views.flatMap((ast) => {
12
+ return doc.parseResult.value.views?.views.flatMap(ast => {
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
14
  const viewId = ElementViewOps.readId(ast);
15
15
  const range = ast.$cstNode?.range;
@@ -27,7 +27,7 @@ export class LikeC4CodeLensProvider {
27
27
  command: {
28
28
  command: 'likec4.open-preview',
29
29
  arguments: [viewId],
30
- title: 'open preview',
30
+ title: 'open preview'
31
31
  }
32
32
  };
33
33
  });
@@ -0,0 +1,13 @@
1
+ import type { LangiumDocument, LangiumDocumentFactory, LangiumSharedServices } from 'langium';
2
+ import { DefaultWorkspaceManager } from 'langium';
3
+ import type { WorkspaceFolder } from 'vscode-languageserver-protocol';
4
+ export declare class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
5
+ protected readonly documentFactory: LangiumDocumentFactory;
6
+ constructor(services: LangiumSharedServices);
7
+ /**
8
+ * Load all additional documents that shall be visible in the context of the given workspace
9
+ * folders and add them to the collector. This can be used to include built-in libraries of
10
+ * your language, which can be either loaded from provided files or constructed in memory.
11
+ */
12
+ protected loadAdditionalDocuments(folders: WorkspaceFolder[], collector: (document: LangiumDocument) => void): Promise<void>;
13
+ }
@@ -0,0 +1,19 @@
1
+ import { DefaultWorkspaceManager } from 'langium';
2
+ import { URI } from 'vscode-uri';
3
+ import * as builtin from '../builtin';
4
+ export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
5
+ documentFactory;
6
+ constructor(services) {
7
+ super(services);
8
+ this.documentFactory = services.workspace.LangiumDocumentFactory;
9
+ }
10
+ /**
11
+ * Load all additional documents that shall be visible in the context of the given workspace
12
+ * folders and add them to the collector. This can be used to include built-in libraries of
13
+ * your language, which can be either loaded from provided files or constructed in memory.
14
+ */
15
+ loadAdditionalDocuments(folders, collector) {
16
+ collector(this.documentFactory.fromString(builtin.specification.document, URI.parse(builtin.specification.uri)));
17
+ return Promise.resolve();
18
+ }
19
+ }
@@ -0,0 +1,2 @@
1
+ export * from './CodeLensProvider';
2
+ export * from './WorkspaceManager';
@@ -0,0 +1,2 @@
1
+ export * from './CodeLensProvider';
2
+ export * from './WorkspaceManager';
@@ -7,8 +7,10 @@ export function createTestServices() {
7
7
  const langiumDocuments = services.shared.workspace.LangiumDocuments;
8
8
  const documentBuilder = services.shared.workspace.DocumentBuilder;
9
9
  const modelBuilder = services.likec4.ModelBuilder;
10
+ const initPromise = services.shared.workspace.WorkspaceManager.initializeWorkspace([]);
10
11
  let documentIndex = 1;
11
12
  const parse = async (input, uri) => {
13
+ await initPromise;
12
14
  uri = uri ?? `${documentIndex++}${metaData.fileExtensions[0]}`;
13
15
  const document = services.shared.workspace.LangiumDocumentFactory.fromString(input, URI.file(uri));
14
16
  langiumDocuments.addDocument(document);
@@ -16,6 +18,7 @@ export function createTestServices() {
16
18
  return document;
17
19
  };
18
20
  const validate = async (input) => {
21
+ await initPromise;
19
22
  const document = typeof input === 'string' ? await parse(input) : input;
20
23
  await documentBuilder.build([document], { validationChecks: 'all' });
21
24
  const diagnostics = document.diagnostics ?? [];
@@ -27,6 +30,7 @@ export function createTestServices() {
27
30
  };
28
31
  };
29
32
  const validateAll = async () => {
33
+ await initPromise;
30
34
  const docs = langiumDocuments.all.toArray();
31
35
  await documentBuilder.build(docs, { validationChecks: 'all' });
32
36
  const diagnostics = docs.flatMap(doc => doc.diagnostics ?? []);
@@ -5,7 +5,7 @@ export const elementChecks = (services) => {
5
5
  if (!fqn) {
6
6
  accept('error', 'Not indexed', {
7
7
  node: el,
8
- property: 'name',
8
+ property: 'name'
9
9
  });
10
10
  return;
11
11
  }
@@ -13,7 +13,7 @@ export const elementChecks = (services) => {
13
13
  if (withSameFqn.length > 1) {
14
14
  accept('error', `Duplicate element name ${el.name !== fqn ? el.name + ' (' + fqn + ')' : el.name}`, {
15
15
  node: el,
16
- property: 'name',
16
+ property: 'name'
17
17
  });
18
18
  }
19
19
  };
@@ -1,4 +1,5 @@
1
1
  import { elementChecks } from './element';
2
+ import { relationChecks } from './relation';
2
3
  import { elementKindChecks, tagChecks } from './specification';
3
4
  import { viewChecks } from './view';
4
5
  export function registerValidationChecks(services) {
@@ -15,6 +16,7 @@ export function registerValidationChecks(services) {
15
16
  ElementView: viewChecks(services),
16
17
  Element: elementChecks(services),
17
18
  ElementKind: elementKindChecks(services),
18
- Tag: tagChecks(services),
19
+ Relation: relationChecks(services),
20
+ Tag: tagChecks(services)
19
21
  });
20
22
  }
@@ -0,0 +1,4 @@
1
+ import type { ValidationCheck } from 'langium';
2
+ import type { ast } from '../ast';
3
+ import type { LikeC4Services } from '../module';
4
+ export declare const relationChecks: (services: LikeC4Services) => ValidationCheck<ast.Relation>;