@likec4/language-server 0.33.1 → 0.35.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.
Files changed (51) hide show
  1. package/contrib/likec4.monarch.ts +17 -3
  2. package/dist/ast.d.ts +24 -11
  3. package/dist/ast.js +12 -9
  4. package/dist/elementRef.d.ts +1 -1
  5. package/dist/elementRef.js +2 -3
  6. package/dist/generated/ast.d.ts +29 -10
  7. package/dist/generated/ast.js +20 -1
  8. package/dist/generated/grammar.d.ts +1 -1
  9. package/dist/generated/grammar.js +11 -11
  10. package/dist/generated/module.d.ts +7 -3
  11. package/dist/generated/module.js +3 -3
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +1 -0
  14. package/dist/logger.d.ts +6 -4
  15. package/dist/logger.js +34 -6
  16. package/dist/{shared → lsp}/CodeLensProvider.d.ts +3 -3
  17. package/dist/{shared → lsp}/DocumentLinkProvider.d.ts +3 -2
  18. package/dist/{shared → lsp}/DocumentLinkProvider.js +3 -3
  19. package/dist/lsp/DocumentSymbolProvider.js +3 -3
  20. package/dist/lsp/index.d.ts +2 -0
  21. package/dist/lsp/index.js +2 -0
  22. package/dist/model/fqn-computation.js +6 -3
  23. package/dist/model/fqn-index.d.ts +4 -7
  24. package/dist/model/fqn-index.js +51 -21
  25. package/dist/model/index.d.ts +1 -0
  26. package/dist/model/index.js +1 -0
  27. package/dist/model/model-builder.d.ts +1 -18
  28. package/dist/model/model-builder.js +111 -340
  29. package/dist/model/model-locator.js +19 -24
  30. package/dist/model/model-parser.d.ts +27 -0
  31. package/dist/model/model-parser.js +293 -0
  32. package/dist/module.d.ts +2 -1
  33. package/dist/module.js +20 -29
  34. package/dist/protocol.d.ts +8 -16
  35. package/dist/protocol.js +2 -6
  36. package/dist/references/scope-computation.js +11 -5
  37. package/dist/references/scope-provider.js +10 -4
  38. package/dist/registerProtocolHandlers.js +33 -17
  39. package/dist/shared/index.d.ts +0 -2
  40. package/dist/shared/index.js +0 -2
  41. package/dist/test/testServices.d.ts +2 -2
  42. package/dist/test/testServices.js +16 -10
  43. package/dist/utils.d.ts +2 -2
  44. package/dist/utils.js +2 -7
  45. package/dist/validation/element.d.ts +1 -1
  46. package/dist/validation/element.js +23 -3
  47. package/dist/validation/index.js +26 -0
  48. package/dist/validation/relation.d.ts +1 -1
  49. package/dist/validation/relation.js +32 -26
  50. package/package.json +10 -8
  51. /package/dist/{shared → lsp}/CodeLensProvider.js +0 -0
@@ -1,5 +1,4 @@
1
- import { nonexhaustive } from '@likec4/core/errors';
2
- import { AsFqn } from '@likec4/core/types';
1
+ import { AsFqn, nonexhaustive } from '@likec4/core';
3
2
  import { MultiMap } from 'langium';
4
3
  import { isEmpty, isNil } from 'remeda';
5
4
  import { ElementOps, ast } from '../ast';
@@ -28,7 +27,11 @@ export function computeDocumentFqn(document, services) {
28
27
  if (ast.isElement(el)) {
29
28
  const fqn = AsFqn(el.name, parent);
30
29
  const path = locator.getAstNodePath(el);
31
- c4fqns.add(fqn, path);
30
+ c4fqns.add(fqn, {
31
+ el: new WeakRef(el),
32
+ path,
33
+ name: el.name
34
+ });
32
35
  ElementOps.writeId(el, fqn);
33
36
  if (!isNil(el.body) && !isEmpty(el.body.elements)) {
34
37
  el.body.elements.forEach(child => traverseStack.push([child, fqn]));
@@ -3,14 +3,15 @@ import type { LangiumDocument, LangiumDocuments, Stream } from 'langium';
3
3
  import type { ast } from '../ast';
4
4
  import { type LikeC4LangiumDocument } from '../ast';
5
5
  import type { LikeC4Services } from '../module';
6
- type FqnIndexedDocument = Omit<LikeC4LangiumDocument, 'c4fqns'> & {
6
+ export type FqnIndexedDocument = Omit<LikeC4LangiumDocument, 'c4fqns'> & {
7
7
  c4fqns: NonNullable<LikeC4LangiumDocument['c4fqns']>;
8
8
  };
9
9
  export declare function isFqnIndexedDocument(doc: LangiumDocument): doc is FqnIndexedDocument;
10
10
  export interface FqnIndexEntry {
11
11
  fqn: Fqn;
12
12
  name: string;
13
- doc: LikeC4LangiumDocument;
13
+ el: ast.Element;
14
+ doc: FqnIndexedDocument;
14
15
  path: string;
15
16
  }
16
17
  export declare class FqnIndex {
@@ -19,15 +20,11 @@ export declare class FqnIndex {
19
20
  private documents;
20
21
  private entries;
21
22
  getFqn(el: ast.Element): Fqn | null;
22
- byFqn(fqn: Fqn): Stream<{
23
- path: string;
24
- doc: LikeC4LangiumDocument;
25
- }>;
23
+ byFqn(fqn: Fqn): Stream<FqnIndexEntry>;
26
24
  directChildrenOf(parent: Fqn): Stream<FqnIndexEntry>;
27
25
  /**
28
26
  * Returns descedant elements with unique names in the scope
29
27
  */
30
28
  uniqueDescedants(parent: Fqn): Stream<FqnIndexEntry>;
31
29
  }
32
- export {};
33
30
  //# sourceMappingURL=fqn-index.d.ts.map
@@ -1,24 +1,48 @@
1
1
  import { nameFromFqn, parentFqn } from '@likec4/core';
2
- import { DONE_RESULT, DocumentState, MultiMap, StreamImpl } from 'langium';
2
+ import { DONE_RESULT, DocumentState, MultiMap, StreamImpl, stream } from 'langium';
3
3
  import { isNil } from 'remeda';
4
4
  import { ElementOps, isLikeC4LangiumDocument } from '../ast';
5
- import { logger } from '../logger';
5
+ import { logError, logger } from '../logger';
6
+ import { printDocs } from '../utils';
6
7
  import { computeDocumentFqn } from './fqn-computation';
7
8
  export function isFqnIndexedDocument(doc) {
8
- return (isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !isNil(doc.c4fqns));
9
+ return isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !isNil(doc.c4fqns);
9
10
  }
10
11
  export class FqnIndex {
11
12
  langiumDocuments;
12
13
  constructor(services) {
13
14
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
15
+ // services.shared.workspace.DocumentBuilder.onUpdate((changed,deleted) => {
16
+ // logger.debug('') // empty line to separate batches
17
+ // logger.debug(`[DocumentBuilder.onUpdate]`)
18
+ // if (changed.length > 0) {
19
+ // logger.debug(` changed:\n` + changed.map(u => ' - ' + Utils.basename(u)).join('\n'))
20
+ // }
21
+ // if (deleted.length > 0) {
22
+ // logger.debug(` deleted:\n` + deleted.map(u => ' - ' + Utils.basename(u)).join('\n'))
23
+ // }
24
+ // })
25
+ services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Changed, (docs, _cancelToken) => {
26
+ logger.debug(`[FqnIndex] onChanged (${docs.length} docs):\n` + printDocs(docs));
27
+ for (const doc of docs) {
28
+ if (isLikeC4LangiumDocument(doc)) {
29
+ delete doc.c4fqns;
30
+ delete doc.c4Elements;
31
+ delete doc.c4Specification;
32
+ delete doc.c4Relations;
33
+ delete doc.c4Views;
34
+ }
35
+ }
36
+ });
14
37
  services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, (docs, _cancelToken) => {
38
+ logger.debug(`[FqnIndex] onIndexedContent ${docs.length}:\n` + printDocs(docs));
15
39
  for (const doc of docs) {
16
40
  if (isLikeC4LangiumDocument(doc)) {
17
41
  try {
18
42
  computeDocumentFqn(doc, services);
19
43
  }
20
44
  catch (e) {
21
- logger.error(e);
45
+ logError(e);
22
46
  }
23
47
  }
24
48
  }
@@ -28,17 +52,26 @@ export class FqnIndex {
28
52
  return this.langiumDocuments.all.filter(isFqnIndexedDocument);
29
53
  }
30
54
  entries() {
31
- return this.documents().flatMap(doc => doc.c4fqns.entries().map(([fqn, path]) => ({ fqn, path, doc })));
55
+ return this.documents().flatMap(doc => doc.c4fqns
56
+ .entries()
57
+ .map(([fqn, entry]) => {
58
+ const el = entry.el.deref();
59
+ if (el) {
60
+ return { ...entry, fqn, el, doc };
61
+ }
62
+ return null;
63
+ })
64
+ .nonNullable());
32
65
  }
33
66
  getFqn(el) {
34
- return ElementOps.readId(el) ?? null;
67
+ return el.fqn ?? ElementOps.readId(el) ?? null;
35
68
  // if (fqn) {
36
69
  // const doc = getDocument(el)
37
70
  // if (isFqnIndexedDocument(doc) && doc.c4fqns.has(fqn)) {
38
71
  // return fqn
39
72
  // }
40
73
  // const path = this.services.workspace.AstNodeLocator.getAstNodePath(el)
41
- // logger.error(`Clean cached FQN ${fqn} at ${path}`)
74
+ // logError(`Clean cached FQN ${fqn} at ${path}`)
42
75
  // ElementOps.writeId(el, null)
43
76
  // fqn = null
44
77
  // }
@@ -46,31 +79,28 @@ export class FqnIndex {
46
79
  }
47
80
  byFqn(fqn) {
48
81
  return this.documents().flatMap(doc => {
49
- return doc.c4fqns.get(fqn).map(path => ({ path, doc }));
82
+ return doc.c4fqns.get(fqn).flatMap(entry => {
83
+ const el = entry.el.deref();
84
+ if (el) {
85
+ return [{ fqn, el, doc, path: entry.path, name: entry.name }];
86
+ }
87
+ return [];
88
+ });
50
89
  });
51
90
  }
52
91
  directChildrenOf(parent) {
53
- return new StreamImpl(() => {
92
+ return stream([parent]).flatMap(_parent => {
54
93
  const children = this.entries()
55
- .filter(e => parentFqn(e.fqn) === parent)
56
- .map((e) => {
57
- const name = nameFromFqn(e.fqn);
58
- const entry = { ...e, name };
59
- return [name, entry];
60
- })
94
+ .filter(e => parentFqn(e.fqn) === _parent)
95
+ .map((entry) => [entry.name, entry])
61
96
  .toArray();
62
97
  if (children.length === 0) {
63
- return null;
98
+ return [];
64
99
  }
65
100
  return new MultiMap(children)
66
101
  .entriesGroupedByKey()
67
102
  .flatMap(([_name, descrs]) => (descrs.length === 1 ? descrs : []))
68
103
  .iterator();
69
- }, iterator => {
70
- if (iterator) {
71
- return iterator.next();
72
- }
73
- return DONE_RESULT;
74
104
  });
75
105
  }
76
106
  /**
@@ -2,4 +2,5 @@ export * from './fqn-computation';
2
2
  export * from './fqn-index';
3
3
  export * from './model-builder';
4
4
  export * from './model-locator';
5
+ export * from './model-parser';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -2,4 +2,5 @@ export * from './fqn-computation';
2
2
  export * from './fqn-index';
3
3
  export * from './model-builder';
4
4
  export * from './model-locator';
5
+ export * from './model-parser';
5
6
  //# sourceMappingURL=index.js.map
@@ -1,30 +1,13 @@
1
- import type * as c4 from '@likec4/core/types';
2
- import { ast } from '../ast';
3
- import type { LikeC4LangiumDocument } from '../ast';
1
+ import { type c4 } from '@likec4/core';
4
2
  import type { LikeC4Services } from '../module';
5
3
  export declare class LikeC4ModelBuilder {
6
4
  private services;
7
- private fqnIndex;
8
5
  private langiumDocuments;
9
6
  private readonly cachedModel;
10
7
  constructor(services: LikeC4Services);
11
8
  private cleanCache;
12
9
  private documents;
13
10
  buildModel(): c4.LikeC4Model | null;
14
- private _buildModel;
15
- /**
16
- * @returns if the document was changed
17
- */
18
- protected parseDocument(doc: LikeC4LangiumDocument): void;
19
- private parseElement;
20
- private parseRelation;
21
- private parseElementExpression;
22
- private parseExpression;
23
- private parseViewRule;
24
- private parseElementView;
25
- protected resolveFqn(node: ast.Element | ast.ExtendElement): c4.Fqn;
26
- private getAstNodePath;
27
- private convertTags;
28
11
  private scheduledCb;
29
12
  private notifyClient;
30
13
  }