@likec4/language-server 0.37.1 → 0.41.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 (60) hide show
  1. package/contrib/likec4.monarch.ts +5 -5
  2. package/contrib/likec4.tmLanguage.json +1 -1
  3. package/dist/Rpc.d.ts +7 -0
  4. package/dist/Rpc.js +130 -0
  5. package/dist/ast.d.ts +20 -0
  6. package/dist/ast.js +169 -141
  7. package/dist/elementRef.js +31 -44
  8. package/dist/generated/ast.d.ts +48 -7
  9. package/dist/generated/ast.js +344 -315
  10. package/dist/generated/grammar.js +2 -3177
  11. package/dist/generated/module.js +13 -18
  12. package/dist/index.js +2 -3
  13. package/dist/logger.js +39 -42
  14. package/dist/lsp/CodeLensProvider.js +28 -32
  15. package/dist/lsp/DocumentLinkProvider.js +26 -33
  16. package/dist/lsp/DocumentSymbolProvider.js +165 -167
  17. package/dist/lsp/HoverProvider.js +35 -48
  18. package/dist/lsp/SemanticTokenProvider.js +160 -201
  19. package/dist/lsp/index.js +5 -6
  20. package/dist/model/fqn-computation.js +39 -40
  21. package/dist/model/fqn-index.js +117 -141
  22. package/dist/model/index.js +5 -6
  23. package/dist/model/model-builder.d.ts +10 -5
  24. package/dist/model/model-builder.js +247 -176
  25. package/dist/model/model-locator.d.ts +1 -1
  26. package/dist/model/model-locator.js +102 -100
  27. package/dist/model/model-parser.d.ts +2 -6
  28. package/dist/model/model-parser.js +284 -286
  29. package/dist/module.d.ts +4 -1
  30. package/dist/module.js +69 -60
  31. package/dist/protocol.d.ts +16 -19
  32. package/dist/protocol.js +14 -22
  33. package/dist/references/index.js +2 -3
  34. package/dist/references/scope-computation.js +72 -69
  35. package/dist/references/scope-provider.js +126 -116
  36. package/dist/shared/WorkspaceManager.d.ts +2 -3
  37. package/dist/shared/WorkspaceManager.js +13 -16
  38. package/dist/shared/index.js +1 -2
  39. package/dist/test/index.js +1 -2
  40. package/dist/test/testServices.js +73 -61
  41. package/dist/utils.d.ts +1 -0
  42. package/dist/utils.js +4 -3
  43. package/dist/validation/element.d.ts +1 -0
  44. package/dist/validation/element.js +31 -38
  45. package/dist/validation/index.js +37 -46
  46. package/dist/validation/relation.js +46 -46
  47. package/dist/validation/specification.d.ts +1 -0
  48. package/dist/validation/specification.js +33 -30
  49. package/dist/validation/view.js +16 -22
  50. package/dist/view-utils/assignNavigateTo.d.ts +3 -0
  51. package/dist/view-utils/assignNavigateTo.js +20 -0
  52. package/dist/view-utils/index.d.ts +4 -0
  53. package/dist/view-utils/index.js +3 -0
  54. package/dist/view-utils/resolve-extended-views.d.ts +7 -0
  55. package/dist/view-utils/resolve-extended-views.js +41 -0
  56. package/dist/view-utils/resolve-relative-paths.d.ts +3 -0
  57. package/dist/view-utils/resolve-relative-paths.js +76 -0
  58. package/package.json +33 -18
  59. package/dist/registerProtocolHandlers.d.ts +0 -3
  60. package/dist/registerProtocolHandlers.js +0 -112
@@ -1,26 +1,21 @@
1
- /******************************************************************************
2
- * This file was generated by langium-cli 2.0.1.
3
- * DO NOT EDIT MANUALLY!
4
- ******************************************************************************/
5
- import { LikeC4AstReflection } from './ast.js';
6
- import { LikeC4Grammar } from './grammar.js';
1
+ import { LikeC4AstReflection } from "./ast.js";
2
+ import { LikeC4Grammar } from "./grammar.js";
7
3
  export const LikeC4LanguageMetaData = {
8
- languageId: 'likec4',
9
- fileExtensions: ['.c4', '.likec4', '.like-c4'],
10
- caseInsensitive: false
4
+ languageId: "likec4",
5
+ fileExtensions: [".c4", ".likec4", ".like-c4"],
6
+ caseInsensitive: false
11
7
  };
12
8
  export const parserConfig = {
13
- recoveryEnabled: true,
14
- nodeLocationTracking: 'full',
9
+ recoveryEnabled: true,
10
+ nodeLocationTracking: "full"
15
11
  };
16
12
  export const LikeC4GeneratedSharedModule = {
17
- AstReflection: () => new LikeC4AstReflection()
13
+ AstReflection: () => new LikeC4AstReflection()
18
14
  };
19
15
  export const LikeC4GeneratedModule = {
20
- Grammar: () => LikeC4Grammar(),
21
- LanguageMetaData: () => LikeC4LanguageMetaData,
22
- parser: {
23
- ParserConfig: () => parserConfig
24
- }
16
+ Grammar: () => LikeC4Grammar(),
17
+ LanguageMetaData: () => LikeC4LanguageMetaData,
18
+ parser: {
19
+ ParserConfig: () => parserConfig
20
+ }
25
21
  };
26
- //# sourceMappingURL=module.js.map
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
- export { logger } from './logger';
2
- export { createLanguageServices } from './module';
3
- //# sourceMappingURL=index.js.map
1
+ export { logger } from "./logger.js";
2
+ export { createLanguageServices } from "./module.js";
package/dist/logger.js CHANGED
@@ -1,50 +1,47 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { normalizeError } from '@likec4/core';
3
- /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
1
+ import { normalizeError } from "@likec4/core";
4
2
  let isSilent = false;
5
3
  export const logger = {
6
- trace(message) {
7
- if (isSilent)
8
- return;
9
- console.trace(message);
10
- },
11
- debug(message) {
12
- if (isSilent)
13
- return;
14
- console.debug(message);
15
- },
16
- info(message) {
17
- if (isSilent)
18
- return;
19
- console.info(message);
20
- },
21
- warn(message) {
22
- if (isSilent)
23
- return;
24
- console.warn(message);
25
- },
26
- error(message) {
27
- if (isSilent)
28
- return;
29
- if (typeof message === 'string') {
30
- console.error(message);
31
- return;
32
- }
33
- console.error(normalizeError(message));
34
- },
35
- silent(silent = true) {
36
- isSilent = silent;
4
+ trace(message) {
5
+ if (isSilent)
6
+ return;
7
+ console.trace(message);
8
+ },
9
+ debug(message) {
10
+ if (isSilent)
11
+ return;
12
+ console.debug(message);
13
+ },
14
+ info(message) {
15
+ if (isSilent)
16
+ return;
17
+ console.info(message);
18
+ },
19
+ warn(message) {
20
+ if (isSilent)
21
+ return;
22
+ console.warn(message);
23
+ },
24
+ error(message) {
25
+ if (isSilent)
26
+ return;
27
+ if (typeof message === "string") {
28
+ console.error(message);
29
+ return;
37
30
  }
31
+ console.error(normalizeError(message));
32
+ },
33
+ silent(silent = true) {
34
+ isSilent = silent;
35
+ }
38
36
  };
39
37
  export function logError(error) {
40
- logger.error(error);
38
+ logger.error(error);
41
39
  }
42
40
  export function logWarnError(err) {
43
- if (typeof err === 'string') {
44
- logger.warn(err);
45
- return;
46
- }
47
- const error = normalizeError(err);
48
- logger.warn(`${error.name}: ${error.message}`);
41
+ if (typeof err === "string") {
42
+ logger.warn(err);
43
+ return;
44
+ }
45
+ const error = normalizeError(err);
46
+ logger.warn(`${error.name}: ${error.message}`);
49
47
  }
50
- //# sourceMappingURL=logger.js.map
@@ -1,36 +1,32 @@
1
- import { ElementViewOps, isParsedLikeC4LangiumDocument } from '../ast';
1
+ import { ElementViewOps, isParsedLikeC4LangiumDocument } from "../ast.js";
2
2
  export class LikeC4CodeLensProvider {
3
- services;
4
- constructor(services) {
5
- this.services = services;
6
- //
3
+ constructor(services) {
4
+ this.services = services;
5
+ }
6
+ provideCodeLens(doc, _params, _cancelToken) {
7
+ if (!isParsedLikeC4LangiumDocument(doc)) {
8
+ return;
7
9
  }
8
- provideCodeLens(doc, _params, _cancelToken) {
9
- if (!isParsedLikeC4LangiumDocument(doc)) {
10
- return;
10
+ return doc.parseResult.value.views?.views.flatMap((ast) => {
11
+ const viewId = ElementViewOps.readId(ast);
12
+ const range = ast.$cstNode?.range;
13
+ if (!range || !viewId) {
14
+ return [];
15
+ }
16
+ return {
17
+ range: {
18
+ start: range.start,
19
+ end: {
20
+ line: range.start.line,
21
+ character: range.start.character + 4
22
+ }
23
+ },
24
+ command: {
25
+ command: "likec4.open-preview",
26
+ arguments: [viewId],
27
+ title: "open preview"
11
28
  }
12
- return doc.parseResult.value.views?.views.flatMap(ast => {
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- const viewId = ElementViewOps.readId(ast);
15
- const range = ast.$cstNode?.range;
16
- if (!range || !viewId) {
17
- return [];
18
- }
19
- return {
20
- range: {
21
- start: range.start,
22
- end: {
23
- line: range.start.line,
24
- character: range.start.character + 4
25
- }
26
- },
27
- command: {
28
- command: 'likec4.open-preview',
29
- arguments: [viewId],
30
- title: 'open preview'
31
- }
32
- };
33
- });
34
- }
29
+ };
30
+ });
31
+ }
35
32
  }
36
- //# sourceMappingURL=CodeLensProvider.js.map
@@ -1,37 +1,30 @@
1
- import { findNodeForProperty, streamAllContents } from 'langium';
2
- import { ast, isParsedLikeC4LangiumDocument } from '../ast';
3
- import { logError } from '../logger';
1
+ import { findNodeForProperty, streamAllContents } from "langium";
2
+ import { ast, isParsedLikeC4LangiumDocument } from "../ast.js";
3
+ import { logError } from "../logger.js";
4
4
  export class LikeC4DocumentLinkProvider {
5
- services;
6
- constructor(services) {
7
- this.services = services;
8
- //
5
+ constructor(services) {
6
+ this.services = services;
7
+ }
8
+ getDocumentLinks(doc, _params) {
9
+ if (!isParsedLikeC4LangiumDocument(doc)) {
10
+ return [];
9
11
  }
10
- getDocumentLinks(doc, _params) {
11
- if (!isParsedLikeC4LangiumDocument(doc)) {
12
- return [];
12
+ const base = new URL(doc.uri.toString());
13
+ return streamAllContents(doc.parseResult.value).filter(ast.isLinkProperty).flatMap((n) => {
14
+ try {
15
+ const u = new URL(n.value, base);
16
+ const valueCst = findNodeForProperty(n.$cstNode, "value");
17
+ if (!valueCst) {
18
+ return [];
13
19
  }
14
- const base = new URL(doc.uri.toString());
15
- return streamAllContents(doc.parseResult.value)
16
- .filter(ast.isLinkProperty)
17
- .flatMap((n) => {
18
- try {
19
- const u = new URL(n.value, base);
20
- const valueCst = findNodeForProperty(n.$cstNode, 'value');
21
- if (!valueCst) {
22
- return [];
23
- }
24
- return {
25
- range: valueCst.range,
26
- target: u.toString()
27
- };
28
- }
29
- catch (e) {
30
- logError(e);
31
- return [];
32
- }
33
- })
34
- .toArray();
35
- }
20
+ return {
21
+ range: valueCst.range,
22
+ target: u.toString()
23
+ };
24
+ } catch (e) {
25
+ logError(e);
26
+ return [];
27
+ }
28
+ }).toArray();
29
+ }
36
30
  }
37
- //# sourceMappingURL=DocumentLinkProvider.js.map
@@ -1,178 +1,176 @@
1
- import { findNodeForProperty } from 'langium';
2
- import { compact, concat, isEmpty, map, pipe } from 'remeda';
3
- import { SymbolKind } from 'vscode-languageserver-protocol';
4
- import { ast } from '../ast';
5
- import { logError } from '../logger';
1
+ import { findNodeForProperty } from "langium";
2
+ import { compact, concat, isEmpty, map, pipe } from "remeda";
3
+ import { SymbolKind } from "vscode-languageserver-protocol";
4
+ import { ast } from "../ast.js";
5
+ import { logError } from "../logger.js";
6
6
  function getElementKindSymbol(astKind) {
7
- if (!astKind.$cstNode || !astKind.kind.$cstNode || isEmpty(astKind.kind.name))
8
- return null;
9
- return {
10
- kind: SymbolKind.Class,
11
- name: astKind.kind.name,
12
- range: astKind.$cstNode.range,
13
- selectionRange: astKind.kind.$cstNode.range
14
- };
7
+ if (!astKind.$cstNode || !astKind.kind.$cstNode || isEmpty(astKind.kind.name))
8
+ return null;
9
+ return {
10
+ kind: SymbolKind.Class,
11
+ name: astKind.kind.name,
12
+ range: astKind.$cstNode.range,
13
+ selectionRange: astKind.kind.$cstNode.range
14
+ };
15
15
  }
16
16
  function getTagSymbol(astTag) {
17
- if (!astTag.$cstNode || !astTag.tag.$cstNode || isEmpty(astTag.tag.name))
18
- return null;
19
- return {
20
- kind: SymbolKind.Interface,
21
- name: '#' + astTag.tag.name,
22
- range: astTag.$cstNode.range,
23
- selectionRange: astTag.tag.$cstNode.range
24
- };
17
+ if (!astTag.$cstNode || !astTag.tag.$cstNode || isEmpty(astTag.tag.name))
18
+ return null;
19
+ return {
20
+ kind: SymbolKind.Interface,
21
+ name: "#" + astTag.tag.name,
22
+ range: astTag.$cstNode.range,
23
+ selectionRange: astTag.tag.$cstNode.range
24
+ };
25
25
  }
26
26
  function getElementViewSymbol(astView) {
27
- const cst = astView?.$cstNode;
28
- if (!cst)
27
+ const cst = astView?.$cstNode;
28
+ if (!cst)
29
+ return [];
30
+ const nameNode = astView.name ? findNodeForProperty(cst, "name") : null;
31
+ if (!nameNode)
32
+ return [];
33
+ return [
34
+ {
35
+ kind: SymbolKind.Class,
36
+ name: nameNode.text,
37
+ range: cst.range,
38
+ selectionRange: nameNode.range,
39
+ children: []
40
+ }
41
+ ];
42
+ }
43
+ export class LikeC4DocumentSymbolProvider {
44
+ constructor(services) {
45
+ this.services = services;
46
+ }
47
+ getSymbols(document) {
48
+ const { specification, model, views } = document.parseResult.value;
49
+ return [
50
+ () => specification && this.getSpecSymbol(specification),
51
+ () => model && this.getModelSymbol(model),
52
+ () => views && this.getModelViewsSymbol(views)
53
+ ].flatMap((fn) => {
54
+ try {
55
+ return fn() ?? [];
56
+ } catch (e) {
57
+ logError(e);
29
58
  return [];
30
- const nameNode = astView.name ? findNodeForProperty(cst, 'name') : null;
59
+ }
60
+ });
61
+ }
62
+ getSpecSymbol(astSpec) {
63
+ const cstModel = astSpec?.$cstNode;
64
+ if (!cstModel)
65
+ return [];
66
+ const specKeywordNode = findNodeForProperty(cstModel, "name");
67
+ if (!specKeywordNode)
68
+ return [];
69
+ const specSymbols = pipe(
70
+ concat(astSpec.elements, astSpec.tags),
71
+ map((nd) => {
72
+ if (ast.isSpecificationElementKind(nd)) {
73
+ return getElementKindSymbol(nd);
74
+ } else {
75
+ return getTagSymbol(nd);
76
+ }
77
+ }),
78
+ compact
79
+ );
80
+ if (specSymbols.length === 0)
81
+ return [];
82
+ return [
83
+ {
84
+ kind: SymbolKind.Namespace,
85
+ name: astSpec.name,
86
+ range: cstModel.range,
87
+ selectionRange: specKeywordNode.range,
88
+ children: specSymbols
89
+ }
90
+ ];
91
+ }
92
+ getModelSymbol(astModel) {
93
+ const cstModel = astModel.$cstNode;
94
+ if (!cstModel)
95
+ return [];
96
+ const nameNode = findNodeForProperty(cstModel, "name");
31
97
  if (!nameNode)
32
- return [];
98
+ return [];
33
99
  return [
34
- {
35
- kind: SymbolKind.Class,
36
- name: nameNode.text,
37
- range: cst.range,
38
- selectionRange: nameNode.range,
39
- children: []
40
- }
100
+ {
101
+ kind: SymbolKind.Namespace,
102
+ name: astModel.name,
103
+ range: cstModel.range,
104
+ selectionRange: nameNode.range,
105
+ children: astModel.elements.flatMap((e) => this.getElementsSymbol(e))
106
+ }
41
107
  ];
42
- }
43
- export class LikeC4DocumentSymbolProvider {
44
- services;
45
- constructor(services) {
46
- this.services = services;
47
- }
48
- getSymbols(document) {
49
- const { specification, model, views } = document.parseResult.value;
50
- return [
51
- () => specification && this.getSpecSymbol(specification),
52
- () => model && this.getModelSymbol(model),
53
- () => views && this.getModelViewsSymbol(views)
54
- ].flatMap(fn => {
55
- try {
56
- return fn() ?? [];
57
- }
58
- catch (e) {
59
- logError(e);
60
- return [];
61
- }
62
- });
63
- }
64
- getSpecSymbol(astSpec) {
65
- const cstModel = astSpec?.$cstNode;
66
- if (!cstModel)
67
- return [];
68
- const specKeywordNode = findNodeForProperty(cstModel, 'name');
69
- if (!specKeywordNode)
70
- return [];
71
- const specSymbols = pipe(concat(astSpec.elements, astSpec.tags), map(nd => {
72
- if (ast.isSpecificationElementKind(nd)) {
73
- return getElementKindSymbol(nd);
74
- }
75
- else {
76
- return getTagSymbol(nd);
77
- }
78
- }), compact);
79
- if (specSymbols.length === 0)
80
- return [];
81
- return [
82
- {
83
- kind: SymbolKind.Namespace,
84
- name: astSpec.name,
85
- range: cstModel.range,
86
- selectionRange: specKeywordNode.range,
87
- children: specSymbols
88
- }
89
- ];
90
- }
91
- getModelSymbol(astModel) {
92
- const cstModel = astModel.$cstNode;
93
- if (!cstModel)
94
- return [];
95
- const nameNode = findNodeForProperty(cstModel, 'name');
96
- if (!nameNode)
97
- return [];
98
- return [
99
- {
100
- kind: SymbolKind.Namespace,
101
- name: astModel.name,
102
- range: cstModel.range,
103
- selectionRange: nameNode.range,
104
- children: astModel.elements.flatMap(e => this.getElementsSymbol(e))
105
- }
106
- ];
107
- }
108
- getElementsSymbol(el) {
109
- try {
110
- if (ast.isExtendElement(el)) {
111
- return this.getExtendElementSymbol(el);
112
- }
113
- if (ast.isElement(el)) {
114
- return this.getElementSymbol(el);
115
- }
116
- }
117
- catch (e) {
118
- logError(e);
119
- }
120
- return [];
121
- }
122
- getExtendElementSymbol(astElement) {
123
- const cst = astElement.$cstNode;
124
- const nameNode = astElement.element.$cstNode;
125
- const body = astElement.body;
126
- if (!cst || !nameNode || !body)
127
- return [];
128
- return [
129
- {
130
- kind: SymbolKind.Constructor,
131
- name: nameNode.text,
132
- range: cst.range,
133
- selectionRange: nameNode.range,
134
- children: body.elements.flatMap(e => this.getElementsSymbol(e))
135
- }
136
- ];
137
- }
138
- getElementSymbol(astElement) {
139
- const cst = astElement.$cstNode;
140
- if (!cst)
141
- return [];
142
- const nameNode = findNodeForProperty(cst, 'name');
143
- if (!nameNode)
144
- return [];
145
- const name = astElement.name;
146
- const kind = astElement.kind.$refText;
147
- // TODO: return the title as well
148
- const detail = kind; // + (astElement.title ? ': ' + astElement.title : '').replaceAll('\n', ' ').trim()
149
- return [
150
- {
151
- kind: SymbolKind.Constructor,
152
- name: name,
153
- range: cst.range,
154
- selectionRange: nameNode.range,
155
- detail,
156
- children: astElement.body?.elements.flatMap(e => this.getElementsSymbol(e)) ?? []
157
- }
158
- ];
159
- }
160
- getModelViewsSymbol(astViews) {
161
- const cst = astViews.$cstNode;
162
- if (!cst)
163
- return [];
164
- const nameNode = findNodeForProperty(cst, 'name');
165
- if (!nameNode)
166
- return [];
167
- return [
168
- {
169
- kind: SymbolKind.Namespace,
170
- name: astViews.name,
171
- range: cst.range,
172
- selectionRange: nameNode.range,
173
- children: astViews.views.flatMap(e => getElementViewSymbol(e))
174
- }
175
- ];
108
+ }
109
+ getElementsSymbol(el) {
110
+ try {
111
+ if (ast.isExtendElement(el)) {
112
+ return this.getExtendElementSymbol(el);
113
+ }
114
+ if (ast.isElement(el)) {
115
+ return this.getElementSymbol(el);
116
+ }
117
+ } catch (e) {
118
+ logError(e);
176
119
  }
120
+ return [];
121
+ }
122
+ getExtendElementSymbol(astElement) {
123
+ const cst = astElement.$cstNode;
124
+ const nameNode = astElement.element.$cstNode;
125
+ const body = astElement.body;
126
+ if (!cst || !nameNode || !body)
127
+ return [];
128
+ return [
129
+ {
130
+ kind: SymbolKind.Constructor,
131
+ name: nameNode.text,
132
+ range: cst.range,
133
+ selectionRange: nameNode.range,
134
+ children: body.elements.flatMap((e) => this.getElementsSymbol(e))
135
+ }
136
+ ];
137
+ }
138
+ getElementSymbol(astElement) {
139
+ const cst = astElement.$cstNode;
140
+ if (!cst)
141
+ return [];
142
+ const nameNode = findNodeForProperty(cst, "name");
143
+ if (!nameNode)
144
+ return [];
145
+ const name = astElement.name;
146
+ const kind = astElement.kind.$refText;
147
+ const detail = kind;
148
+ return [
149
+ {
150
+ kind: SymbolKind.Constructor,
151
+ name,
152
+ range: cst.range,
153
+ selectionRange: nameNode.range,
154
+ detail,
155
+ children: astElement.body?.elements.flatMap((e) => this.getElementsSymbol(e)) ?? []
156
+ }
157
+ ];
158
+ }
159
+ getModelViewsSymbol(astViews) {
160
+ const cst = astViews.$cstNode;
161
+ if (!cst)
162
+ return [];
163
+ const nameNode = findNodeForProperty(cst, "name");
164
+ if (!nameNode)
165
+ return [];
166
+ return [
167
+ {
168
+ kind: SymbolKind.Namespace,
169
+ name: astViews.name,
170
+ range: cst.range,
171
+ selectionRange: nameNode.range,
172
+ children: astViews.views.flatMap((e) => getElementViewSymbol(e))
173
+ }
174
+ ];
175
+ }
177
176
  }
178
- //# sourceMappingURL=DocumentSymbolProvider.js.map