@likec4/language-server 0.23.0 → 0.25.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.
@@ -5,7 +5,7 @@
5
5
  ******************************************************************************/
6
6
  /// <reference types="react" />
7
7
  import { type DocumentSymbolProvider, type MaybePromise } from 'langium';
8
- import { type DocumentSymbol } from 'vscode-languageserver';
8
+ import { type DocumentSymbol } from 'vscode-languageserver-protocol';
9
9
  import { type LikeC4LangiumDocument, ast } from '../ast';
10
10
  import type { LikeC4Services } from '../module';
11
11
  export declare class LikeC4DocumentSymbolProvider implements DocumentSymbolProvider {
@@ -5,7 +5,7 @@
5
5
  ******************************************************************************/
6
6
  import invariant from 'tiny-invariant';
7
7
  import { findNodeForProperty } from 'langium';
8
- import { SymbolKind } from 'vscode-languageserver';
8
+ import { SymbolKind } from 'vscode-languageserver-protocol';
9
9
  import { ast } from '../ast';
10
10
  import { logger } from '../logger';
11
11
  export class LikeC4DocumentSymbolProvider {
@@ -1,5 +1,5 @@
1
1
  import { type AstNode, AstNodeHoverProvider, type MaybePromise } from 'langium';
2
- import type { Hover } from 'vscode-languageserver';
2
+ import type { Hover } from 'vscode-languageserver-protocol';
3
3
  import type { LikeC4Services } from '../module';
4
4
  export declare class LikeC4HoverProvider extends AstNodeHoverProvider {
5
5
  private locator;
@@ -1,5 +1,5 @@
1
1
  import { AbstractSemanticTokenProvider } from 'langium';
2
- import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver';
2
+ import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver-protocol';
3
3
  import { ast } from '../ast';
4
4
  import { isElementRefHead } from '../elementRef';
5
5
  export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
@@ -7,7 +7,8 @@ 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
+ modifier: [SemanticTokenModifiers.defaultLibrary]
11
12
  });
12
13
  if (ast.isElementRef(node) || ast.isStrictElementRef(node)) {
13
14
  acceptor({
@@ -25,11 +26,17 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
25
26
  });
26
27
  return;
27
28
  }
28
- if (ast.isRelationExpression(node) ||
29
+ if (ast.isRelation(node) ||
30
+ ast.isRelationExpression(node) ||
29
31
  ast.isIncomingExpression(node) ||
32
+ ast.isInOutExpression(node) ||
30
33
  ast.isOutgoingExpression(node)) {
31
- keyword('->');
32
- return;
34
+ acceptor({
35
+ node,
36
+ property: 'arr',
37
+ type: SemanticTokenTypes.keyword,
38
+ modifier: [SemanticTokenModifiers.defaultLibrary]
39
+ });
33
40
  }
34
41
  if (ast.isElementKindExpression(node) || ast.isElementTagExpression(node)) {
35
42
  keyword('element');
@@ -54,13 +61,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
54
61
  return;
55
62
  }
56
63
  }
57
- if (ast.isInOutExpression(node)) {
58
- keyword('->', 0);
59
- keyword('->', 1);
60
- return;
61
- }
62
64
  if (ast.isRelation(node)) {
63
- keyword('->');
64
65
  if ('title' in node) {
65
66
  acceptor({
66
67
  node,
@@ -102,11 +103,16 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
102
103
  node,
103
104
  property: 'key',
104
105
  type: SemanticTokenTypes.keyword
106
+ // type: SemanticTokenTypes.property,
107
+ // modifier: [
108
+ // SemanticTokenModifiers.readonly,
109
+ // SemanticTokenModifiers.declaration
110
+ // ]
105
111
  });
106
112
  acceptor({
107
113
  node,
108
114
  property: 'value',
109
- type: SemanticTokenTypes.enumMember
115
+ type: SemanticTokenTypes.enum
110
116
  });
111
117
  return;
112
118
  }
@@ -115,6 +121,11 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
115
121
  node,
116
122
  property: 'key',
117
123
  type: SemanticTokenTypes.keyword
124
+ // type: SemanticTokenTypes.property,
125
+ // modifier: [
126
+ // SemanticTokenModifiers.readonly,
127
+ // SemanticTokenModifiers.declaration
128
+ // ]
118
129
  });
119
130
  acceptor({
120
131
  node,
@@ -151,20 +162,8 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
151
162
  type: SemanticTokenTypes.keyword,
152
163
  modifier: []
153
164
  });
154
- if ('title' in node) {
155
- acceptor({
156
- node,
157
- property: 'title',
158
- type: SemanticTokenTypes.string
159
- });
160
- }
161
165
  }
162
166
  highlightView(node, acceptor) {
163
- acceptor({
164
- node,
165
- keyword: 'view',
166
- type: SemanticTokenTypes.keyword
167
- });
168
167
  if (node.name) {
169
168
  acceptor({
170
169
  node,
@@ -12,7 +12,7 @@ export declare class LikeC4ModelBuilder {
12
12
  /**
13
13
  * @returns if the document was changed
14
14
  */
15
- protected parseDocument(doc: LikeC4LangiumDocument): boolean;
15
+ protected parseDocument(doc: LikeC4LangiumDocument): void;
16
16
  private parseElement;
17
17
  private parseRelation;
18
18
  private parseElementExpression;
@@ -22,6 +22,7 @@ export declare class LikeC4ModelBuilder {
22
22
  protected resolveFqn(node: ast.Element | ast.ExtendElement): c4.Fqn;
23
23
  private getAstNodePath;
24
24
  private convertTags;
25
+ private scheduledCb;
25
26
  private notifyClient;
26
27
  }
27
28
  //# sourceMappingURL=model-builder.d.ts.map
@@ -6,11 +6,12 @@ import objectHash from 'object-hash';
6
6
  import { clone, isNil } from 'rambdax';
7
7
  import * as R from 'remeda';
8
8
  import invariant from 'tiny-invariant';
9
- import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle } from '../ast';
9
+ import { ElementViewOps, ast, cleanParsedModel, isLikeC4LangiumDocument, isValidLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle } from '../ast';
10
10
  import { elementRef, strictElementRefFqn } from '../elementRef';
11
11
  import { logger } from '../logger';
12
12
  import { Rpc } from '../protocol';
13
13
  import { failExpectedNever } from '../utils';
14
+ import stripIndent from 'strip-indent';
14
15
  export class LikeC4ModelBuilder {
15
16
  services;
16
17
  fqnIndex;
@@ -25,17 +26,20 @@ export class LikeC4ModelBuilder {
25
26
  if (cancelToken.isCancellationRequested) {
26
27
  break;
27
28
  }
29
+ if (!isLikeC4LangiumDocument(doc)) {
30
+ continue;
31
+ }
32
+ countOfChangedDocs++;
28
33
  try {
29
- if (isLikeC4LangiumDocument(doc) && this.parseDocument(doc)) {
30
- countOfChangedDocs++;
31
- }
34
+ this.parseDocument(doc);
32
35
  }
33
36
  catch (e) {
34
37
  logger.error(`Error parsing document ${doc.uri.toString()}`);
38
+ logger.error(e);
35
39
  }
36
40
  }
37
41
  if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
38
- void this.notifyClient();
42
+ this.notifyClient();
39
43
  }
40
44
  });
41
45
  }
@@ -43,7 +47,7 @@ export class LikeC4ModelBuilder {
43
47
  return this.services.shared.lsp.Connection;
44
48
  }
45
49
  documents() {
46
- return this.langiumDocuments.all.toArray().filter(isParsedLikeC4LangiumDocument);
50
+ return this.langiumDocuments.all.toArray().filter(isValidLikeC4LangiumDocument);
47
51
  }
48
52
  buildModel() {
49
53
  const docs = this.documents();
@@ -56,7 +60,7 @@ export class LikeC4ModelBuilder {
56
60
  const c4Specification = {
57
61
  kinds: {}
58
62
  };
59
- R.pipe(R.map(docs, R.prop('c4Specification')), R.forEach(spec => Object.assign(c4Specification.kinds, spec.kinds)));
63
+ R.forEach(R.map(docs, R.prop('c4Specification')), spec => Object.assign(c4Specification.kinds, spec.kinds));
60
64
  const toModelElement = (el) => {
61
65
  const kind = c4Specification.kinds[el.kind];
62
66
  if (kind) {
@@ -166,9 +170,9 @@ export class LikeC4ModelBuilder {
166
170
  }
167
171
  }
168
172
  }
169
- const prevHash = doc.c4hash ?? '';
170
- doc.c4hash = c4hash(doc);
171
- return prevHash !== doc.c4hash;
173
+ // const prevHash = doc.c4hash ?? ''
174
+ // doc.c4hash = c4hash(doc)
175
+ // return prevHash !== doc.c4hash
172
176
  }
173
177
  parseElement(astNode) {
174
178
  const id = this.resolveFqn(astNode);
@@ -189,7 +193,7 @@ export class LikeC4ModelBuilder {
189
193
  astPath,
190
194
  title: title ?? astNode.name,
191
195
  ...(technology && { technology }),
192
- ...(description && { description }),
196
+ ...(description && { description: stripIndent(description).trim() }),
193
197
  ...(tags.length > 0 ? { tags } : {}),
194
198
  ...(shape && shape !== DefaultElementShape ? { shape } : {}),
195
199
  ...(color && color !== DefaultThemeColor ? { color } : {})
@@ -331,12 +335,21 @@ export class LikeC4ModelBuilder {
331
335
  convertTags(el) {
332
336
  return el.tags?.value.map(tagRef => tagRef.ref?.name) ?? [];
333
337
  }
334
- async notifyClient() {
338
+ scheduledCb = null;
339
+ notifyClient() {
335
340
  const connection = this.connection;
336
341
  if (!connection) {
337
342
  return;
338
343
  }
339
- await connection.sendNotification(Rpc.onDidChangeModel);
344
+ if (this.scheduledCb) {
345
+ logger.debug('debounce scheduled onDidChangeModel');
346
+ clearTimeout(this.scheduledCb);
347
+ }
348
+ this.scheduledCb = setTimeout(() => {
349
+ logger.debug('send onDidChangeModel');
350
+ this.scheduledCb = null;
351
+ void connection.sendNotification(Rpc.onDidChangeModel, '');
352
+ }, 350);
340
353
  }
341
354
  }
342
355
  //# sourceMappingURL=model-builder.js.map
package/dist/module.js CHANGED
@@ -6,6 +6,7 @@ import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
6
6
  import { registerProtocolHandlers } from './registerProtocolHandlers';
7
7
  import { LikeC4CodeLensProvider, LikeC4WorkspaceManager } from './shared';
8
8
  import { registerValidationChecks } from './validation';
9
+ import { logger } from './logger';
9
10
  function bind(Type) {
10
11
  return (services) => new Type(services);
11
12
  }
@@ -39,15 +40,29 @@ const LikeC4SharedModule = {
39
40
  }
40
41
  };
41
42
  export function createLanguageServices(context) {
42
- // const connection = context.connection
43
- // if (connection) {
44
- // logger.log = connection.console.log.bind(connection.console)
45
- // logger.info = connection.console.info.bind(connection.console)
46
- // logger.warn = connection.console.warn.bind(connection.console)
47
- // logger.error = connection.console.error.bind(connection.console)
48
- // logger.debug = connection.tracer.log.bind(connection.tracer)
49
- // logger.trace = connection.tracer.log.bind(connection.tracer)
50
- // }
43
+ const connection = context?.connection;
44
+ if (connection) {
45
+ const log = (method) => (message) => {
46
+ try {
47
+ console[method](message);
48
+ connection.console[method](String(message));
49
+ if (method === 'error') {
50
+ connection.telemetry.logEvent({ eventName: 'error', message });
51
+ }
52
+ }
53
+ catch (error) {
54
+ console.error(error);
55
+ }
56
+ };
57
+ logger.log = log('log');
58
+ logger.info = log('info');
59
+ logger.warn = log('warn');
60
+ logger.error = log('error');
61
+ logger.trace = logger.debug = (message) => {
62
+ console.debug(message);
63
+ connection.tracer.log(message);
64
+ };
65
+ }
51
66
  const moduleContext = {
52
67
  ...EmptyFileSystem,
53
68
  ...context
@@ -1,6 +1,6 @@
1
1
  import type { Fqn, LikeC4Model, RelationID, ViewID } from '@likec4/core';
2
2
  import type { DocumentUri, Location } from 'vscode-languageserver-protocol';
3
- import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
3
+ import { NotificationType, RequestType0, RequestType } from 'vscode-languageserver-protocol';
4
4
  interface BuildDocumentsParams {
5
5
  docs: DocumentUri[];
6
6
  }
@@ -16,7 +16,7 @@ export declare const locateView: RequestType<{
16
16
  id: ViewID;
17
17
  }, Location | null, void>;
18
18
  export declare const Rpc: {
19
- readonly onDidChangeModel: NotificationType0;
19
+ readonly onDidChangeModel: NotificationType<string>;
20
20
  readonly fetchModel: RequestType0<{
21
21
  model: LikeC4Model | null;
22
22
  }, void>;
package/dist/protocol.js CHANGED
@@ -1,6 +1,6 @@
1
- import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
1
+ import { NotificationType, RequestType0, RequestType } from 'vscode-languageserver-protocol';
2
2
  //#region From server
3
- const onDidChangeModel = new NotificationType0('likec4/onDidChangeModel');
3
+ const onDidChangeModel = new NotificationType('likec4/onDidChangeModel');
4
4
  //#endregion
5
5
  //#region To server
6
6
  const fetchModel = new RequestType0('likec4/fetchModel');
@@ -18,19 +18,17 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
18
18
  docExports.push(this.descriptions.createDescription(tag, '#' + tag.name, document));
19
19
  }
20
20
  }
21
+ // Filled later by FqnIndex (on IndexedContent phase)
21
22
  document.c4fqns = undefined;
22
- if (model) {
23
+ // Only root model elements are exported
24
+ if (model && model.elements.length > 0) {
23
25
  for (const elAst of model.elements) {
24
26
  if (ast.isElement(elAst)) {
25
27
  docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
26
28
  }
27
29
  }
28
30
  }
29
- // const c4fqns = document.c4fqns
30
- // logger.debug(`doc ${document.uri.path}:
31
- // fqns: ${c4fqns ? Array.from(c4fqns.keys()).join(', ') : '--'}
32
- // `)
33
- if (views) {
31
+ if (views && views.views.length > 0) {
34
32
  for (const viewAst of views.views) {
35
33
  if ('name' in viewAst) {
36
34
  docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
@@ -67,29 +67,14 @@ We rebuild: [
67
67
  }
68
68
  await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
69
69
  });
70
- connection.onRequest(Rpc.locateElement, async ({ element, property }, _cancelToken) => {
71
- try {
72
- return Promise.resolve(modelLocator.locateElement(element, property ?? 'name'));
73
- }
74
- catch (e) {
75
- return Promise.reject(e);
76
- }
70
+ connection.onRequest(Rpc.locateElement, ({ element, property }) => {
71
+ return modelLocator.locateElement(element, property ?? 'name');
77
72
  });
78
- connection.onRequest(Rpc.locateRelation, ({ id }, _cancelToken) => {
79
- try {
80
- return Promise.resolve(modelLocator.locateRelation(id));
81
- }
82
- catch (e) {
83
- return Promise.reject(e);
84
- }
73
+ connection.onRequest(Rpc.locateRelation, ({ id }) => {
74
+ return modelLocator.locateRelation(id);
85
75
  });
86
- connection.onRequest(Rpc.locateView, ({ id }, _cancelToken) => {
87
- try {
88
- return Promise.resolve(modelLocator.locateView(id));
89
- }
90
- catch (e) {
91
- return Promise.reject(e);
92
- }
76
+ connection.onRequest(Rpc.locateView, ({ id }) => {
77
+ return modelLocator.locateView(id);
93
78
  });
94
79
  }
95
80
  //# sourceMappingURL=registerProtocolHandlers.js.map