@likec4/language-server 0.23.0 → 0.24.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/ast.d.ts CHANGED
@@ -46,7 +46,6 @@ export declare const ElementOps: {
46
46
  readId(node: ast.Element): c4.Fqn | undefined;
47
47
  };
48
48
  export interface LikeC4LangiumDocument extends LangiumDocument<LikeC4Document> {
49
- c4hash?: string;
50
49
  c4Specification: ParsedAstSpecification;
51
50
  c4Elements: ParsedAstElement[];
52
51
  c4Relations: ParsedAstRelation[];
@@ -61,7 +60,7 @@ export declare function cleanParsedModel(doc: LikeC4LangiumDocument): {
61
60
  };
62
61
  export declare function isLikeC4LangiumDocument(doc: LangiumDocument): doc is LikeC4LangiumDocument;
63
62
  export declare function isParsedLikeC4LangiumDocument(doc: LangiumDocument): doc is LikeC4LangiumDocument;
64
- export declare const isValidDocument: (doc: LangiumDocument) => doc is LikeC4LangiumDocument;
63
+ export declare const isValidLikeC4LangiumDocument: (doc: LangiumDocument) => doc is LikeC4LangiumDocument;
65
64
  export declare function streamModel(doc: LikeC4LangiumDocument): Generator<ast.Relation | ast.Element, void, unknown>;
66
65
  export declare function resolveRelationPoints(node: ast.Relation): {
67
66
  source: ast.Element;
package/dist/ast.js CHANGED
@@ -63,8 +63,8 @@ export function isParsedLikeC4LangiumDocument(doc) {
63
63
  return (isLikeC4LangiumDocument(doc) &&
64
64
  ['c4Specification', 'c4Elements', 'c4Relations', 'c4Views'].every(key => key in doc));
65
65
  }
66
- export const isValidDocument = (doc) => {
67
- if (!isLikeC4LangiumDocument(doc))
66
+ export const isValidLikeC4LangiumDocument = (doc) => {
67
+ if (!isParsedLikeC4LangiumDocument(doc))
68
68
  return false;
69
69
  const { state, parseResult, diagnostics } = doc;
70
70
  return (state === DocumentState.Validated &&
@@ -87,7 +87,7 @@ export function* streamModel(doc) {
87
87
  }
88
88
  continue;
89
89
  }
90
- if (ast.isElement(el) && el.body && el.body.elements.length > 0) {
90
+ if (el.body && el.body.elements.length > 0) {
91
91
  for (const nested of el.body.elements) {
92
92
  if (ast.isRelation(nested)) {
93
93
  relations.push(nested);
@@ -121,9 +121,8 @@ export function resolveRelationPoints(node) {
121
121
  if (!ast.isElementBody(node.$container)) {
122
122
  throw new Error('Skip relation due to invalid reference to source');
123
123
  }
124
- const source = node.$container.$container;
125
124
  return {
126
- source,
125
+ source: node.$container.$container,
127
126
  target
128
127
  };
129
128
  }
@@ -35,6 +35,7 @@ export function parentStrictElementRef(node) {
35
35
  path.unshift(parent.el.$refText);
36
36
  parent = parent.$container;
37
37
  }
38
+ invariant(path.length > 0, 'Expected non-empty parent path');
38
39
  return path.join('.');
39
40
  }
40
41
  //# sourceMappingURL=elementRef.js.map
@@ -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,7 +6,7 @@ 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';
@@ -25,17 +25,20 @@ export class LikeC4ModelBuilder {
25
25
  if (cancelToken.isCancellationRequested) {
26
26
  break;
27
27
  }
28
+ if (!isLikeC4LangiumDocument(doc)) {
29
+ continue;
30
+ }
31
+ countOfChangedDocs++;
28
32
  try {
29
- if (isLikeC4LangiumDocument(doc) && this.parseDocument(doc)) {
30
- countOfChangedDocs++;
31
- }
33
+ this.parseDocument(doc);
32
34
  }
33
35
  catch (e) {
34
36
  logger.error(`Error parsing document ${doc.uri.toString()}`);
37
+ logger.error(e);
35
38
  }
36
39
  }
37
40
  if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
38
- void this.notifyClient();
41
+ this.notifyClient();
39
42
  }
40
43
  });
41
44
  }
@@ -43,7 +46,7 @@ export class LikeC4ModelBuilder {
43
46
  return this.services.shared.lsp.Connection;
44
47
  }
45
48
  documents() {
46
- return this.langiumDocuments.all.toArray().filter(isParsedLikeC4LangiumDocument);
49
+ return this.langiumDocuments.all.toArray().filter(isValidLikeC4LangiumDocument);
47
50
  }
48
51
  buildModel() {
49
52
  const docs = this.documents();
@@ -56,7 +59,7 @@ export class LikeC4ModelBuilder {
56
59
  const c4Specification = {
57
60
  kinds: {}
58
61
  };
59
- R.pipe(R.map(docs, R.prop('c4Specification')), R.forEach(spec => Object.assign(c4Specification.kinds, spec.kinds)));
62
+ R.forEach(R.map(docs, R.prop('c4Specification')), spec => Object.assign(c4Specification.kinds, spec.kinds));
60
63
  const toModelElement = (el) => {
61
64
  const kind = c4Specification.kinds[el.kind];
62
65
  if (kind) {
@@ -166,9 +169,9 @@ export class LikeC4ModelBuilder {
166
169
  }
167
170
  }
168
171
  }
169
- const prevHash = doc.c4hash ?? '';
170
- doc.c4hash = c4hash(doc);
171
- return prevHash !== doc.c4hash;
172
+ // const prevHash = doc.c4hash ?? ''
173
+ // doc.c4hash = c4hash(doc)
174
+ // return prevHash !== doc.c4hash
172
175
  }
173
176
  parseElement(astNode) {
174
177
  const id = this.resolveFqn(astNode);
@@ -331,12 +334,21 @@ export class LikeC4ModelBuilder {
331
334
  convertTags(el) {
332
335
  return el.tags?.value.map(tagRef => tagRef.ref?.name) ?? [];
333
336
  }
334
- async notifyClient() {
337
+ scheduledCb = null;
338
+ notifyClient() {
335
339
  const connection = this.connection;
336
340
  if (!connection) {
337
341
  return;
338
342
  }
339
- await connection.sendNotification(Rpc.onDidChangeModel);
343
+ if (this.scheduledCb) {
344
+ logger.debug('debounce scheduled onDidChangeModel');
345
+ clearTimeout(this.scheduledCb);
346
+ }
347
+ this.scheduledCb = setTimeout(() => {
348
+ this.scheduledCb = null;
349
+ logger.debug('send onDidChangeModel');
350
+ void connection.sendNotification(Rpc.onDidChangeModel);
351
+ }, 300);
340
352
  }
341
353
  }
342
354
  //# 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,26 @@ 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
+ }
50
+ catch (error) {
51
+ console.error(error);
52
+ }
53
+ };
54
+ logger.log = log('log');
55
+ logger.info = log('info');
56
+ logger.warn = log('warn');
57
+ logger.error = log('error');
58
+ logger.trace = logger.debug = (message) => {
59
+ console.debug(message);
60
+ connection.tracer.log(message);
61
+ };
62
+ }
51
63
  const moduleContext = {
52
64
  ...EmptyFileSystem,
53
65
  ...context
@@ -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));
@@ -69,23 +69,23 @@ We rebuild: [
69
69
  });
70
70
  connection.onRequest(Rpc.locateElement, async ({ element, property }, _cancelToken) => {
71
71
  try {
72
- return Promise.resolve(modelLocator.locateElement(element, property ?? 'name'));
72
+ return modelLocator.locateElement(element, property ?? 'name');
73
73
  }
74
74
  catch (e) {
75
75
  return Promise.reject(e);
76
76
  }
77
77
  });
78
- connection.onRequest(Rpc.locateRelation, ({ id }, _cancelToken) => {
78
+ connection.onRequest(Rpc.locateRelation, async ({ id }, _cancelToken) => {
79
79
  try {
80
- return Promise.resolve(modelLocator.locateRelation(id));
80
+ return modelLocator.locateRelation(id);
81
81
  }
82
82
  catch (e) {
83
83
  return Promise.reject(e);
84
84
  }
85
85
  });
86
- connection.onRequest(Rpc.locateView, ({ id }, _cancelToken) => {
86
+ connection.onRequest(Rpc.locateView, async ({ id }, _cancelToken) => {
87
87
  try {
88
- return Promise.resolve(modelLocator.locateView(id));
88
+ return modelLocator.locateView(id);
89
89
  }
90
90
  catch (e) {
91
91
  return Promise.reject(e);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likec4/language-server",
3
3
  "description": "LikeC4 Language Server",
4
- "version": "0.23.0",
4
+ "version": "0.24.0",
5
5
  "license": "MIT",
6
6
  "bugs": "https://github.com/likec4/likec4/issues",
7
7
  "homepage": "https://likec4.dev",
@@ -58,7 +58,7 @@
58
58
  "test:watch": "run -T vitest"
59
59
  },
60
60
  "dependencies": {
61
- "@likec4/core": "0.23.0",
61
+ "@likec4/core": "0.24.0",
62
62
  "langium": "^1.2.1",
63
63
  "nanoid": "^4.0.2",
64
64
  "object-hash": "^3.0.0",