@likec4/language-server 0.8.0 → 0.18.1

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.
@@ -1,7 +1,7 @@
1
1
  // Monarch syntax highlighting for the likec4 language.
2
2
  export default {
3
3
  keywords: [
4
- 'BottomTop','LeftRight','RightLeft','TopBottom','autoLayout','browser','color','cylinder','description','element','exclude','extend','include','it','model','muted','of','person','primary','queue','rectangle','secondary','shape','specification','storage','style','tag','technology','this','title','view','views'
4
+ 'BottomTop','LeftRight','RightLeft','TopBottom','amber','autoLayout','blue','browser','color','cylinder','description','element','exclude','extend','gray','green','include','indigo','it','mobile','model','muted','of','person','primary','queue','rectangle','red','secondary','shape','sky','slate','specification','storage','style','tag','technology','this','title','view','views'
5
5
  ],
6
6
  operators: [
7
7
  '*','->','.*'
@@ -12,7 +12,7 @@
12
12
  },
13
13
  {
14
14
  "name": "keyword.control.likec4",
15
- "match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|autoLayout|browser|color|cylinder|description|element|exclude|extend|include|it|model|muted|of|person|primary|queue|rectangle|secondary|shape|specification|storage|style|tag|technology|this|title|view|views)\\b"
15
+ "match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|amber|autoLayout|blue|browser|color|cylinder|description|element|exclude|extend|gray|green|include|indigo|it|mobile|model|muted|of|person|primary|queue|rectangle|red|secondary|shape|sky|slate|specification|storage|style|tag|technology|this|title|view|views)\\b"
16
16
  },
17
17
  {
18
18
  "name": "string.quoted.double.likec4",
@@ -1,8 +1,9 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
- import { AstNode, AbstractAstReflection, Reference, ReferenceInfo, TypeMetaData } from 'langium';
5
+ import type { AstNode, Reference, ReferenceInfo, TypeMetaData } from 'langium';
6
+ import { AbstractAstReflection } from 'langium';
6
7
  export type AnyStringProperty = ElementStringProperty | RelationStringProperty | ViewProperty;
7
8
  export declare const AnyStringProperty = "AnyStringProperty";
8
9
  export declare function isAnyStringProperty(item: unknown): item is AnyStringProperty;
@@ -15,14 +16,14 @@ export declare function isElementExpression(item: unknown): item is ElementExpre
15
16
  export type ElementProperty = ElementStringProperty | ElementStyleProperty;
16
17
  export declare const ElementProperty = "ElementProperty";
17
18
  export declare function isElementProperty(item: unknown): item is ElementProperty;
18
- export type ElementShape = 'browser' | 'cylinder' | 'person' | 'queue' | 'rectangle' | 'storage';
19
+ export type ElementShape = 'browser' | 'cylinder' | 'mobile' | 'person' | 'queue' | 'rectangle' | 'storage';
19
20
  export declare function isElementShape(item: unknown): item is ElementShape;
20
21
  export type Expression = ElementExpression | InOutExpression | IncomingExpression | OutgoingExpression | RelationExpression;
21
22
  export declare const Expression = "Expression";
22
23
  export declare function isExpression(item: unknown): item is Expression;
23
24
  export type Name = 'element' | 'model' | ElementShape | ThemeColor | string;
24
25
  export declare function isName(item: unknown): item is Name;
25
- export type ThemeColor = 'muted' | 'primary' | 'secondary';
26
+ export type ThemeColor = 'amber' | 'blue' | 'gray' | 'green' | 'indigo' | 'muted' | 'primary' | 'red' | 'secondary' | 'sky' | 'slate';
26
27
  export declare function isThemeColor(item: unknown): item is ThemeColor;
27
28
  export type View = ElementView;
28
29
  export declare const View = "View";
@@ -1,8 +1,7 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
- /* eslint-disable */
6
5
  import { AbstractAstReflection } from 'langium';
7
6
  export const AnyStringProperty = 'AnyStringProperty';
8
7
  export function isAnyStringProperty(item) {
@@ -21,7 +20,7 @@ export function isElementProperty(item) {
21
20
  return reflection.isInstance(item, ElementProperty);
22
21
  }
23
22
  export function isElementShape(item) {
24
- return item === 'rectangle' || item === 'person' || item === 'browser' || item === 'cylinder' || item === 'storage' || item === 'queue';
23
+ return item === 'rectangle' || item === 'person' || item === 'browser' || item === 'mobile' || item === 'cylinder' || item === 'storage' || item === 'queue';
25
24
  }
26
25
  export const Expression = 'Expression';
27
26
  export function isExpression(item) {
@@ -31,7 +30,7 @@ export function isName(item) {
31
30
  return isElementShape(item) || isThemeColor(item) || item === 'element' || item === 'model' || (typeof item === 'string' && (/((([^\W\d_])|(_))((([^\W\d_])|([0-9]))|(_))*)/.test(item)));
32
31
  }
33
32
  export function isThemeColor(item) {
34
- return item === 'primary' || item === 'secondary' || item === 'muted';
33
+ return item === 'primary' || item === 'secondary' || item === 'muted' || item === 'slate' || item === 'blue' || item === 'indigo' || item === 'sky' || item === 'red' || item === 'gray' || item === 'green' || item === 'amber';
35
34
  }
36
35
  export const View = 'View';
37
36
  export function isView(item) {
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
- import { Grammar } from 'langium';
5
+ import type { Grammar } from 'langium';
6
6
  export declare const LikeC4Grammar: () => Grammar;
7
7
  //# sourceMappingURL=grammar.d.ts.map
@@ -1,5 +1,5 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
5
  import { loadGrammarFromJson } from 'langium';
@@ -2059,6 +2059,38 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
2059
2059
  {
2060
2060
  "$type": "Keyword",
2061
2061
  "value": "muted"
2062
+ },
2063
+ {
2064
+ "$type": "Keyword",
2065
+ "value": "slate"
2066
+ },
2067
+ {
2068
+ "$type": "Keyword",
2069
+ "value": "blue"
2070
+ },
2071
+ {
2072
+ "$type": "Keyword",
2073
+ "value": "indigo"
2074
+ },
2075
+ {
2076
+ "$type": "Keyword",
2077
+ "value": "sky"
2078
+ },
2079
+ {
2080
+ "$type": "Keyword",
2081
+ "value": "red"
2082
+ },
2083
+ {
2084
+ "$type": "Keyword",
2085
+ "value": "gray"
2086
+ },
2087
+ {
2088
+ "$type": "Keyword",
2089
+ "value": "green"
2090
+ },
2091
+ {
2092
+ "$type": "Keyword",
2093
+ "value": "amber"
2062
2094
  }
2063
2095
  ]
2064
2096
  },
@@ -2088,6 +2120,10 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
2088
2120
  "$type": "Keyword",
2089
2121
  "value": "browser"
2090
2122
  },
2123
+ {
2124
+ "$type": "Keyword",
2125
+ "value": "mobile"
2126
+ },
2091
2127
  {
2092
2128
  "$type": "Keyword",
2093
2129
  "value": "cylinder"
@@ -1,8 +1,8 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
- import { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, LanguageMetaData, Module, IParserConfig } from 'langium';
5
+ import type { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, LanguageMetaData, Module, IParserConfig } from 'langium';
6
6
  export declare const LikeC4LanguageMetaData: LanguageMetaData;
7
7
  export declare const parserConfig: IParserConfig;
8
8
  export declare const LikeC4GeneratedSharedModule: Module<LangiumSharedServices, LangiumGeneratedSharedServices>;
@@ -1,8 +1,7 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 1.2.0.
2
+ * This file was generated by langium-cli 1.2.1.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
- import 'langium';
6
5
  import { LikeC4AstReflection } from './ast';
7
6
  import { LikeC4Grammar } from './grammar';
8
7
  export const LikeC4LanguageMetaData = {
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export { createLanguageServices } from './module';
2
2
  export type { LikeC4Services } from './module';
3
- export * as protocol from './protocol';
4
3
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
1
  export { createLanguageServices } from './module';
2
- export * as protocol from './protocol';
3
2
  //# sourceMappingURL=index.js.map
@@ -135,46 +135,9 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
135
135
  if (ast.isElement(node)) {
136
136
  return this.highlightAstElement(node, acceptor);
137
137
  }
138
- // if (ast.isExtendElement(node)) {
139
- // keyword('extend')
140
- // return
141
- // }
142
- // if (ast.isElementProperty(node) || ast.isRelationProperty(node) || ast.isViewProperty(node)) {
143
- // acceptor({
144
- // node,
145
- // property: 'key',
146
- // type: SemanticTokenTypes.property,
147
- // modifier: [SemanticTokenModifiers.definition]
148
- // })
149
- // if ('value' in node) {
150
- // acceptor({
151
- // node,
152
- // property: 'value',
153
- // type: SemanticTokenTypes.string
154
- // })
155
- // }
156
- // return
157
- // }
158
138
  if (ast.isView(node)) {
159
139
  return this.highlightView(node, acceptor);
160
140
  }
161
- // if (ast.isDynamicViewSteps(node)) {
162
- // keyword('steps')
163
- // return
164
- // }
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
- // //
178
141
  }
179
142
  highlightAstElement(node, acceptor) {
180
143
  acceptor({
@@ -198,11 +161,17 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
198
161
  }
199
162
  }
200
163
  highlightView(node, acceptor) {
164
+ acceptor({
165
+ node,
166
+ keyword: 'view',
167
+ type: SemanticTokenTypes.keyword
168
+ });
201
169
  if (node.name) {
202
170
  acceptor({
203
171
  node,
204
172
  property: 'name',
205
- type: SemanticTokenTypes.variable
173
+ type: SemanticTokenTypes.variable,
174
+ modifier: [SemanticTokenModifiers.declaration]
206
175
  });
207
176
  }
208
177
  if (node.viewOf) {
@@ -212,11 +181,6 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
212
181
  type: SemanticTokenTypes.keyword
213
182
  });
214
183
  }
215
- acceptor({
216
- node,
217
- keyword: 'view',
218
- type: SemanticTokenTypes.keyword
219
- });
220
184
  }
221
185
  }
222
186
  //# sourceMappingURL=SemanticTokenProvider.js.map
@@ -5,11 +5,11 @@ import { isEmpty, isNil } from 'rambdax';
5
5
  import { ElementOps, ast } from '../ast';
6
6
  import { strictElementRefFqn } from '../elementRef';
7
7
  export function computeDocumentFqn(document, services) {
8
+ const c4fqns = document.c4fqns = new MultiMap();
8
9
  const { model } = document.parseResult.value;
9
10
  if (!model?.elements) {
10
11
  return;
11
12
  }
12
- const c4fqns = document.c4fqns = new MultiMap();
13
13
  const locator = services.workspace.AstNodeLocator;
14
14
  const traverseStack = model.elements.map(el => [el, null]);
15
15
  let pair;
@@ -1,10 +1,10 @@
1
+ import type { Fqn } from '@likec4/core/types';
2
+ import type { LangiumDocuments } from 'langium';
1
3
  import { DocumentState, MultiMap, StreamImpl } from 'langium';
2
- import type { URI } from 'vscode-uri';
4
+ import type { SetNonNullable } from 'type-fest';
3
5
  import type { ast } from '../ast';
4
6
  import { type LikeC4LangiumDocument } from '../ast';
5
7
  import type { LikeC4Services } from '../module';
6
- import type { Fqn } from '@likec4/core/types';
7
- import type { SetNonNullable } from 'type-fest';
8
8
  export interface FqnIndexEntry {
9
9
  fqn: Fqn;
10
10
  name: string;
@@ -13,6 +13,7 @@ export interface FqnIndexEntry {
13
13
  }
14
14
  export declare class FqnIndex {
15
15
  private services;
16
+ protected langiumDocuments: LangiumDocuments;
16
17
  constructor(services: LikeC4Services);
17
18
  private documents;
18
19
  private entries;
@@ -25,7 +26,7 @@ export declare class FqnIndex {
25
26
  c4Elements: import("../ast").ParsedAstElement[];
26
27
  c4Relations: import("../ast").ParsedAstRelation[];
27
28
  c4Views: import("../ast").ParsedAstElementView[];
28
- readonly uri: URI;
29
+ readonly uri: import("vscode-uri").URI;
29
30
  readonly textDocument: import("vscode-languageserver-textdocument").TextDocument;
30
31
  state: DocumentState;
31
32
  parseResult: import("langium").ParseResult<ast.LikeC4Document>;
@@ -1,59 +1,39 @@
1
+ import { nameFromFqn, parentFqn } from '@likec4/core/utils';
1
2
  import { DocumentState, DONE_RESULT, getDocument, MultiMap, StreamImpl } from 'langium';
3
+ import { isNil } from 'rambdax';
2
4
  import { ElementOps, isLikeC4LangiumDocument } from '../ast';
3
5
  import { logger } from '../logger';
4
- import { nameFromFqn, parentFqn } from '@likec4/core/utils';
5
- import '../elementRef';
6
- import { isNil } from 'rambdax';
7
- import '../generated/ast';
8
- const isFqnIndexedDocument = (doc) => isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.ComputedScopes && !isNil(doc.c4fqns);
6
+ import { computeDocumentFqn } from './fqn-computation';
7
+ const isFqnIndexedDocument = (doc) => isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !isNil(doc.c4fqns);
9
8
  export class FqnIndex {
10
9
  services;
11
- // #fqnMap = new WeakMap<ast.Element, Fqn>()
12
- // protected readonly descriptions: AstNodeDescriptionProvider
10
+ langiumDocuments;
13
11
  constructor(services) {
14
12
  this.services = services;
15
- // this.descriptions = services.workspace.AstNodeDescriptionProvider
16
- // services.shared.workspace.DocumentBuilder.onUpdate((_changed, removed) => {
17
- // for (const uri of [..._changed, ...removed]) {
18
- // this.cleanIndexedElements(uri)
19
- // }
20
- // })
21
- // services.shared.workspace.DocumentBuilder.onBuildPhase(
22
- // DocumentState.Parsed,
23
- // (docs, _cancelToken) => {
24
- // for (const doc of docs) {
25
- // this.cleanIndexedElements(doc.uri)
26
- // this.doIndexElements(doc as LikeC4LangiumDocument)
27
- // }
28
- // }
29
- // )
13
+ this.langiumDocuments = services.shared.workspace.LangiumDocuments;
14
+ services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, (docs, _cancelToken) => {
15
+ for (const doc of docs) {
16
+ if (isLikeC4LangiumDocument(doc)) {
17
+ try {
18
+ computeDocumentFqn(doc, services);
19
+ }
20
+ catch (e) {
21
+ logger.error(e);
22
+ }
23
+ }
24
+ }
25
+ });
30
26
  }
31
27
  documents() {
32
- return this.services.shared.workspace.LangiumDocuments.all.filter(isFqnIndexedDocument);
28
+ return this.langiumDocuments.all.filter(isFqnIndexedDocument);
33
29
  }
34
30
  entries() {
35
31
  return this.documents().flatMap(doc => doc.c4fqns.entries().map(([fqn, path]) => ({ fqn, path, doc })));
36
32
  }
37
- // private index() {
38
- // const index = new MultiMap<Fqn, {
39
- // path: string,
40
- // doc: LikeC4LangiumDocument
41
- // }>()
42
- // this.entries().toMap()
43
- // this.entries().forEach(({ fqn, path, doc }) => {
44
- // index.add(fqn, { path, doc })
45
- // })
46
- // // for (const doc of this.documents()) {
47
- // // doc.c4fqns.entries().forEach(([fqn, path]) => {
48
- // // index.add(fqn, { path, doc })
49
- // // })
50
- // // }
51
- // return index
52
- // }
53
33
  get(el) {
54
34
  let fqn = ElementOps.readId(el) ?? null;
55
- const doc = getDocument(el);
56
35
  if (fqn) {
36
+ const doc = getDocument(el);
57
37
  if (isFqnIndexedDocument(doc) && doc.c4fqns.has(fqn)) {
58
38
  return fqn;
59
39
  }
@@ -1,3 +1,4 @@
1
+ export * from './fqn-computation';
1
2
  export * from './fqn-index';
2
3
  export * from './model-builder';
3
4
  export * from './model-locator';
@@ -1,3 +1,4 @@
1
+ export * from './fqn-computation';
1
2
  export * from './fqn-index';
2
3
  export * from './model-builder';
3
4
  export * from './model-locator';
@@ -2,12 +2,11 @@ import { computeViews } from '@likec4/core/compute-view';
2
2
  import { DefaultElementShape, DefaultThemeColor } from '@likec4/core/types';
3
3
  import { compareByFqnHierarchically, parentFqn } from '@likec4/core/utils';
4
4
  import { A, O, flow, pipe } from '@mobily/ts-belt';
5
- import { DocumentState, getDocument, interruptAndCheck } from 'langium';
5
+ import { DocumentState, getDocument } from 'langium';
6
6
  import objectHash from 'object-hash';
7
- import { clone, isNil, mergeDeepRight, omit, reduce } from 'rambdax';
7
+ import { clone, isNil, mergeDeepRight, reduce } from 'rambdax';
8
8
  import invariant from 'tiny-invariant';
9
- import { toAutoLayout } from '../ast';
10
- import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toElementStyle } from '../ast';
9
+ import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle } from '../ast';
11
10
  import { elementRef, strictElementRefFqn } from '../elementRef';
12
11
  import { logger } from '../logger';
13
12
  import { Rpc } from '../protocol';
@@ -20,26 +19,24 @@ export class LikeC4ModelBuilder {
20
19
  this.services = services;
21
20
  this.fqnIndex = services.likec4.FqnIndex;
22
21
  this.langiumDocuments = services.shared.workspace.LangiumDocuments;
23
- services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, async (docs, cancelToken) => {
22
+ services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, (docs, cancelToken) => {
24
23
  let countOfChangedDocs = 0;
25
- try {
26
- for (const doc of docs) {
27
- await interruptAndCheck(cancelToken);
28
- try {
29
- if (isLikeC4LangiumDocument(doc) && this.parseDocument(doc)) {
30
- countOfChangedDocs++;
31
- }
32
- }
33
- catch (e) {
34
- logger.warn(`Error parsing document ${doc.uri.toString()}`);
24
+ for (const doc of docs) {
25
+ if (cancelToken.isCancellationRequested) {
26
+ break;
27
+ }
28
+ try {
29
+ if (isLikeC4LangiumDocument(doc) && this.parseDocument(doc)) {
30
+ countOfChangedDocs++;
35
31
  }
36
32
  }
37
- }
38
- finally {
39
- if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
40
- await this.notifyClient();
33
+ catch (e) {
34
+ logger.warn(`Error parsing document ${doc.uri.toString()}`);
41
35
  }
42
36
  }
37
+ if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
38
+ void this.notifyClient();
39
+ }
43
40
  });
44
41
  }
45
42
  get connection() {
@@ -51,8 +48,10 @@ export class LikeC4ModelBuilder {
51
48
  buildModel() {
52
49
  const docs = this.documents();
53
50
  if (docs.length === 0) {
51
+ logger.debug('No documents to build model from');
54
52
  return;
55
53
  }
54
+ // TODO:
56
55
  try {
57
56
  const c4Specification = reduce((acc, doc) => mergeDeepRight(acc, doc.c4Specification), {
58
57
  kinds: {}
@@ -65,22 +64,25 @@ export class LikeC4ModelBuilder {
65
64
  const toModelElement = (el) => {
66
65
  const kind = c4Specification.kinds[el.kind];
67
66
  if (kind) {
67
+ const { astPath, ...model } = el;
68
68
  return {
69
69
  ...(kind.shape !== DefaultElementShape ? { shape: kind.shape } : {}),
70
70
  ...(kind.color !== DefaultThemeColor ? { color: kind.color } : {}),
71
- ...omit(['astPath'], el)
71
+ ...model
72
72
  };
73
73
  }
74
74
  return null;
75
75
  };
76
76
  const toModelRelation = (rel) => {
77
- return omit(['astPath'], rel);
77
+ const { astPath, ...model } = rel;
78
+ return model;
78
79
  };
79
80
  const elements = pipe(docs.flatMap(d => d.c4Elements), A.filterMap(flow(toModelElement, O.fromNullable)), A.sort(compareByFqnHierarchically), A.reduce({}, (acc, el) => {
80
81
  const parent = parentFqn(el.id);
81
82
  if (!parent || parent in acc) {
82
83
  if (el.id in acc) {
83
84
  logger.warn(`Duplicate element id: ${el.id}`);
85
+ return acc;
84
86
  }
85
87
  acc[el.id] = el;
86
88
  }
@@ -89,24 +91,30 @@ export class LikeC4ModelBuilder {
89
91
  const relations = pipe(docs.flatMap(d => d.c4Relations), A.filterMap(flow(toModelRelation, O.fromPredicate(({ source, target }) => source in elements && target in elements))), A.reduce({}, (acc, el) => {
90
92
  if (el.id in acc) {
91
93
  logger.warn(`Duplicate relation id: ${el.id}`);
94
+ return acc;
92
95
  }
93
96
  acc[el.id] = el;
94
97
  return acc;
95
98
  }));
96
99
  const toModelView = (view) => {
97
- let title = view.title;
100
+ // eslint-disable-next-line prefer-const
101
+ let { astPath, rules, title, ...model } = view;
98
102
  if (!title && view.viewOf) {
99
103
  title = elements[view.viewOf]?.title;
100
104
  }
105
+ if (!title && view.id === 'index') {
106
+ title = 'Landscape view';
107
+ }
101
108
  return {
102
- ...omit(['astPath', 'rules', 'title'], view),
103
- ...(!!title ? { title } : {}),
104
- rules: clone(view.rules)
109
+ ...model,
110
+ ...(title && { title }),
111
+ rules: clone(rules)
105
112
  };
106
113
  };
107
114
  const views = pipe(docs.flatMap(d => d.c4Views), A.filterMap(flow(toModelView, O.fromPredicate(v => isNil(v.viewOf) || v.viewOf in elements))), A.reduce({}, (acc, v) => {
108
115
  if (v.id in acc) {
109
116
  logger.warn(`Duplicate view id: ${v.id}`);
117
+ return acc;
110
118
  }
111
119
  acc[v.id] = v;
112
120
  return acc;
@@ -332,7 +340,6 @@ export class LikeC4ModelBuilder {
332
340
  if (!connection) {
333
341
  return;
334
342
  }
335
- logger.debug('Send onDidChangeModel');
336
343
  await connection.sendNotification(Rpc.onDidChangeModel);
337
344
  }
338
345
  }
@@ -1,5 +1,5 @@
1
1
  import type * as c4 from '@likec4/core/types';
2
- import type { Location } from 'vscode-languageserver';
2
+ import type { Location } from 'vscode-languageserver-protocol';
3
3
  import type { ParsedAstElement } from '../ast';
4
4
  import { ast } from '../ast';
5
5
  import type { LikeC4Services } from '../module';
package/dist/module.js CHANGED
@@ -14,10 +14,6 @@ export const LikeC4Module = {
14
14
  FqnIndex: bind(FqnIndex),
15
15
  ModelBuilder: bind(LikeC4ModelBuilder),
16
16
  ModelLocator: bind(LikeC4ModelLocator)
17
- // Model: bind(LikeC4Model),
18
- // Model: bind(LikeC4Model),
19
- // SpecIndex: bind(LikeC4SpecIndex),
20
- // Validator: bind(LikeC4Validator)
21
17
  },
22
18
  lsp: {
23
19
  DocumentSymbolProvider: bind(LikeC4DocumentSymbolProvider),
@@ -1,14 +1,9 @@
1
1
  import type { Fqn, LikeC4Model, RelationID, ViewID } from '@likec4/core';
2
2
  import type { DocumentUri, Location } from 'vscode-languageserver-protocol';
3
3
  import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
4
- export declare const onDidChangeModel: NotificationType0;
5
- export declare const fetchModel: RequestType0<{
6
- model: LikeC4Model | null;
7
- }, void>;
8
- export interface BuildDocumentsParams {
4
+ interface BuildDocumentsParams {
9
5
  docs: DocumentUri[];
10
6
  }
11
- export declare const buildDocuments: RequestType<BuildDocumentsParams, void, void>;
12
7
  export interface LocateElementParams {
13
8
  element: Fqn;
14
9
  property?: string;
@@ -25,6 +20,9 @@ export declare const Rpc: {
25
20
  readonly fetchModel: RequestType0<{
26
21
  model: LikeC4Model | null;
27
22
  }, void>;
23
+ readonly rebuild: RequestType0<{
24
+ docs: DocumentUri[];
25
+ }, void>;
28
26
  readonly buildDocuments: RequestType<BuildDocumentsParams, void, void>;
29
27
  readonly locateElement: RequestType<LocateElementParams, Location | null, void>;
30
28
  readonly locateRelation: RequestType<{
@@ -34,4 +32,5 @@ export declare const Rpc: {
34
32
  id: ViewID;
35
33
  }, Location | null, void>;
36
34
  };
35
+ export {};
37
36
  //# sourceMappingURL=protocol.d.ts.map
package/dist/protocol.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
2
2
  //#region From server
3
- export const onDidChangeModel = new NotificationType0('likec4/onDidChangeModel');
3
+ const onDidChangeModel = new NotificationType0('likec4/onDidChangeModel');
4
4
  //#endregion
5
5
  //#region To server
6
- export const fetchModel = new RequestType0('likec4/fetchModel');
7
- export const buildDocuments = new RequestType('likec4/buildDocuments');
6
+ const fetchModel = new RequestType0('likec4/fetchModel');
7
+ const rebuild = new RequestType0('likec4/rebuildModel');
8
+ const buildDocuments = new RequestType('likec4/buildDocuments');
8
9
  export const locateElement = new RequestType('likec4/locateElement');
9
10
  export const locateRelation = new RequestType('likec4/locateRelation');
10
11
  export const locateView = new RequestType('likec4/locateView');
@@ -12,6 +13,7 @@ export const locateView = new RequestType('likec4/locateView');
12
13
  export const Rpc = {
13
14
  onDidChangeModel,
14
15
  fetchModel,
16
+ rebuild,
15
17
  buildDocuments,
16
18
  locateElement,
17
19
  locateRelation,
@@ -1,6 +1,5 @@
1
1
  import { DefaultScopeComputation, MultiMap } from 'langium';
2
2
  import { ast } from '../ast';
3
- import { computeDocumentFqn } from './fqn-computation';
4
3
  export class LikeC4ScopeComputation extends DefaultScopeComputation {
5
4
  services;
6
5
  constructor(services) {
@@ -26,7 +25,6 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
26
25
  docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
27
26
  }
28
27
  }
29
- computeDocumentFqn(document, this.services);
30
28
  }
31
29
  // const c4fqns = document.c4fqns
32
30
  // logger.debug(`doc ${document.uri.path}:
@@ -1,3 +1,4 @@
1
+ import { URI } from 'vscode-uri';
1
2
  import { logger } from './logger';
2
3
  import { Rpc } from './protocol';
3
4
  export function registerProtocolHandlers(services) {
@@ -17,24 +18,53 @@ export function registerProtocolHandlers(services) {
17
18
  model = null;
18
19
  logger.error(e);
19
20
  }
20
- return Promise.resolve({
21
- model: model ?? null
22
- });
21
+ return Promise.resolve({ model });
22
+ });
23
+ connection.onRequest(Rpc.rebuild, async (cancelToken) => {
24
+ const changed = LangiumDocuments.all.map(d => d.uri).toArray();
25
+ logger.debug(`Rebuild all documents: [
26
+ ${changed.map(d => d.toString()).join('\n ')}
27
+ ]`);
28
+ await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
29
+ return {
30
+ docs: changed.map(d => d.toString())
31
+ };
23
32
  });
24
33
  connection.onRequest(Rpc.buildDocuments, async ({ docs }, cancelToken) => {
34
+ if (docs.length === 0) {
35
+ logger.debug(`Received empty request to rebuild`);
36
+ return;
37
+ }
38
+ logger.debug(`Received request to rebuild: [
39
+ ${docs.join('\n ')}
40
+ ]`);
25
41
  const changed = [];
26
42
  for (const d of docs) {
27
- const uri = d;
28
- if (LangiumDocuments.hasDocument(uri)) {
29
- changed.push(uri);
43
+ try {
44
+ const uri = URI.parse(d);
45
+ if (LangiumDocuments.hasDocument(uri)) {
46
+ changed.push(uri);
47
+ }
48
+ else {
49
+ logger.warn(`LangiumDocuments does not have document: ${d}`);
50
+ LangiumDocuments.getOrCreateDocument(uri);
51
+ }
30
52
  }
31
- else {
32
- logger.error(`LangiumDocuments does not have document: ${uri.toString()}`);
53
+ catch (e) {
54
+ logger.error(e);
33
55
  }
34
56
  }
35
- logger.debug(`Received request to rebuild: [
36
- ${changed.map(d => d.toString()).join('\n ')}
37
- ]`);
57
+ if (changed.length !== docs.length) {
58
+ const all = LangiumDocuments.all.map(d => d.uri.toString()).toArray();
59
+ logger.warn(`
60
+ We have in LangiumDocuments: [
61
+ ${all.join('\n ')}
62
+ ]
63
+ We rebuild: [
64
+ ${changed.join('\n ')}
65
+ ]
66
+ `.trim());
67
+ }
38
68
  await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
39
69
  });
40
70
  connection.onRequest(Rpc.locateElement, async ({ element, property }, _cancelToken) => {
@@ -11,6 +11,12 @@ export const elementChecks = (services) => {
11
11
  }
12
12
  const withSameFqn = fqnIndex.byFqn(fqn).limit(2).count();
13
13
  if (withSameFqn > 1) {
14
+ // console.error(withSameFqn.map(e => ({
15
+ // fqn,
16
+ // name: el.name,
17
+ // path: e.path,
18
+ // doc: e.doc.uri.toString()
19
+ // })))
14
20
  accept('error', `Duplicate element name ${el.name !== fqn ? el.name + ' (' + fqn + ')' : el.name}`, {
15
21
  node: el,
16
22
  property: 'name'
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.8.0",
4
+ "version": "0.18.1",
5
5
  "license": "MIT",
6
6
  "bugs": "https://github.com/likec4/likec4/issues",
7
7
  "homepage": "https://likec4.dev",
@@ -11,8 +11,7 @@
11
11
  "contrib",
12
12
  "!**/__mocks__/",
13
13
  "!**/__test__/",
14
- "!**/*.spec.js",
15
- "!**/*.spec.d.ts",
14
+ "!**/*.spec.*",
16
15
  "!**/*.map"
17
16
  ],
18
17
  "repository": {
@@ -29,11 +28,6 @@
29
28
  "types": "./dist/index.d.ts",
30
29
  "import": "./dist/index.js",
31
30
  "require": "./dist/index.js"
32
- },
33
- "./builtin": {
34
- "types": "./dist/builtin.d.ts",
35
- "import": "./dist/builtin.js",
36
- "require": "./dist/builtin.js"
37
31
  }
38
32
  },
39
33
  "publishConfig": {
@@ -47,11 +41,6 @@
47
41
  "types": "./dist/index.d.ts",
48
42
  "import": "./dist/index.js",
49
43
  "require": "./dist/index.js"
50
- },
51
- "./builtin": {
52
- "types": "./dist/builtin.d.ts",
53
- "import": "./dist/builtin.js",
54
- "require": "./dist/builtin.js"
55
44
  }
56
45
  }
57
46
  },
@@ -65,11 +54,11 @@
65
54
  "dev": "run-p 'watch:*'",
66
55
  "lint": "run -T eslint src/ --fix",
67
56
  "clean": "run -T rimraf dist contrib",
68
- "test": "vitest run",
69
- "test:watch": "vitest"
57
+ "test": "run -T vitest run",
58
+ "test:watch": "run -T vitest"
70
59
  },
71
60
  "dependencies": {
72
- "@likec4/core": "0.7.0",
61
+ "@likec4/core": "0.18.1",
73
62
  "@mobily/ts-belt": "^3.13.1",
74
63
  "langium": "^1.2.0",
75
64
  "nanoid": "^4.0.2",
@@ -77,17 +66,15 @@
77
66
  "rambdax": "^9.1.1",
78
67
  "strip-indent": "^4.0.0",
79
68
  "tiny-invariant": "^1.3.1",
80
- "type-fest": "^3.9.0",
69
+ "type-fest": "^3.11.1",
81
70
  "vscode-languageserver": "~8.1.0",
82
71
  "vscode-languageserver-protocol": "~3.17.3"
83
72
  },
84
73
  "devDependencies": {
85
74
  "@types/node": "^18.15.11",
86
75
  "@types/object-hash": "^3.0.2",
87
- "langium-cli": "^1.2.0",
76
+ "langium-cli": "^1.2.1",
88
77
  "npm-run-all": "^4.1.5",
89
- "typescript": "^5.0.4",
90
- "vite": "^4.3.3",
91
- "vitest": "^0.31.0"
78
+ "typescript": "^5.1.3"
92
79
  }
93
80
  }
package/dist/builtin.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export declare const specification: {
2
- uri: string;
3
- document: string;
4
- };
5
- //# sourceMappingURL=builtin.d.ts.map
package/dist/builtin.js DELETED
@@ -1,9 +0,0 @@
1
- export const specification = {
2
- uri: 'builtin:///specification.likec4',
3
- document: `
4
- specification {
5
- element element
6
- }
7
- `.trimStart()
8
- };
9
- //# sourceMappingURL=builtin.js.map
File without changes