@likec4/language-server 1.30.0 → 1.32.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 (80) hide show
  1. package/dist/LikeC4LanguageServices.d.ts +2 -1
  2. package/dist/LikeC4LanguageServices.js +4 -3
  3. package/dist/Rpc.js +11 -4
  4. package/dist/ast.d.ts +11 -15
  5. package/dist/bundled.mjs +2545 -2475
  6. package/dist/formatting/LikeC4Formatter.d.ts +26 -2
  7. package/dist/formatting/LikeC4Formatter.js +106 -8
  8. package/dist/generated/ast.d.ts +171 -153
  9. package/dist/generated/ast.js +40 -18
  10. package/dist/generated/grammar.d.ts +1 -1
  11. package/dist/generated/grammar.js +1 -1
  12. package/dist/generated/module.d.ts +1 -1
  13. package/dist/lsp/CompletionProvider.js +1 -1
  14. package/dist/lsp/DocumentLinkProvider.js +4 -3
  15. package/dist/lsp/HoverProvider.js +9 -1
  16. package/dist/lsp/SemanticTokenProvider.js +18 -4
  17. package/dist/mcp/LikeC4MCPServerFactory.d.ts +5 -2
  18. package/dist/mcp/LikeC4MCPServerFactory.js +2 -72
  19. package/dist/mcp/LikeC4MCPTools.js +5 -3
  20. package/dist/mcp/sseserver/MCPServerFactory.d.ts +8 -0
  21. package/dist/mcp/sseserver/MCPServerFactory.js +78 -0
  22. package/dist/mcp/sseserver/with-mcp-server.d.ts +2 -0
  23. package/dist/mcp/sseserver/with-mcp-server.js +5 -1
  24. package/dist/mcp/utils.d.ts +5 -4
  25. package/dist/mcp/utils.js +2 -2
  26. package/dist/model/builder/MergedExtends.d.ts +4 -4
  27. package/dist/model/builder/MergedExtends.js +1 -1
  28. package/dist/model/builder/MergedSpecification.d.ts +4 -3
  29. package/dist/model/builder/MergedSpecification.js +9 -8
  30. package/dist/model/builder/assignTagColors.d.ts +7 -0
  31. package/dist/model/builder/assignTagColors.js +51 -0
  32. package/dist/model/builder/buildModel.d.ts +2 -2
  33. package/dist/model/builder/buildModel.js +40 -18
  34. package/dist/model/deployments-index.js +2 -2
  35. package/dist/model/fqn-index.d.ts +1 -1
  36. package/dist/model/fqn-index.js +6 -6
  37. package/dist/model/model-builder.d.ts +10 -4
  38. package/dist/model/model-builder.js +22 -19
  39. package/dist/model/model-locator.d.ts +10 -2
  40. package/dist/model/model-locator.js +65 -9
  41. package/dist/model/model-parser-where.d.ts +1 -1
  42. package/dist/model/model-parser-where.js +1 -1
  43. package/dist/model/model-parser.d.ts +10 -11
  44. package/dist/model/model-parser.js +11 -7
  45. package/dist/model/parser/Base.js +2 -3
  46. package/dist/model/parser/DeploymentModelParser.d.ts +1 -1
  47. package/dist/model/parser/DeploymentModelParser.js +7 -5
  48. package/dist/model/parser/DeploymentViewParser.d.ts +3 -3
  49. package/dist/model/parser/DeploymentViewParser.js +2 -1
  50. package/dist/model/parser/FqnRefParser.d.ts +1 -1
  51. package/dist/model/parser/FqnRefParser.js +2 -5
  52. package/dist/model/parser/GlobalsParser.d.ts +23 -24
  53. package/dist/model/parser/GlobalsParser.js +4 -4
  54. package/dist/model/parser/ModelParser.d.ts +1 -1
  55. package/dist/model/parser/ModelParser.js +1 -1
  56. package/dist/model/parser/PredicatesParser.d.ts +12 -12
  57. package/dist/model/parser/SpecificationParser.d.ts +5 -2
  58. package/dist/model/parser/SpecificationParser.js +18 -30
  59. package/dist/model/parser/ViewsParser.d.ts +23 -23
  60. package/dist/model/parser/ViewsParser.js +12 -19
  61. package/dist/model-change/changeElementStyle.d.ts +2 -2
  62. package/dist/model-change/changeElementStyle.js +6 -2
  63. package/dist/module.d.ts +1 -1
  64. package/dist/module.js +5 -2
  65. package/dist/protocol.d.ts +24 -3
  66. package/dist/protocol.js +4 -0
  67. package/dist/references/scope-computation.js +2 -3
  68. package/dist/test/testServices.d.ts +15 -0
  69. package/dist/test/testServices.js +4 -1
  70. package/dist/validation/relation.js +1 -1
  71. package/dist/validation/specification.js +1 -1
  72. package/dist/view-utils/assignNavigateTo.d.ts +1 -1
  73. package/dist/view-utils/assignNavigateTo.js +3 -3
  74. package/dist/views/likec4-views.d.ts +1 -3
  75. package/dist/views/likec4-views.js +68 -44
  76. package/dist/workspace/WorkspaceManager.d.ts +2 -2
  77. package/dist/workspace/WorkspaceManager.js +2 -2
  78. package/package.json +27 -25
  79. /package/dist/mcp/sseserver/{SSELikeC4MCPServer.d.ts → MCPServer.d.ts} +0 -0
  80. /package/dist/mcp/sseserver/{SSELikeC4MCPServer.js → MCPServer.js} +0 -0
@@ -1,9 +1,25 @@
1
- import { type AstNode } from 'langium';
2
- import { AbstractFormatter } from 'langium/lsp';
1
+ import { type AstNode, type LangiumDocument } from 'langium';
2
+ import { AbstractFormatter, FormattingRegion } from 'langium/lsp';
3
+ import type { FormattingOptions as LSFormattingOptions, Range, TextEdit } from 'vscode-languageserver-types';
4
+ import type { LikeC4Services } from '../module';
5
+ type QuoteStyle = 'single' | 'double' | 'ignore' | 'auto';
6
+ interface LikeC4FormatterOptions {
7
+ quoteStyle: QuoteStyle;
8
+ }
9
+ type ExtendedFormattingCommandType = 'normalizeQuotes';
10
+ interface ExtendedFormattingCommand {
11
+ type: ExtendedFormattingCommandType;
12
+ region: FormattingRegion;
13
+ }
3
14
  export declare class LikeC4Formatter extends AbstractFormatter {
15
+ protected options: LikeC4FormatterOptions;
16
+ extendedFormattingCommands: ExtendedFormattingCommand[];
17
+ constructor(services: LikeC4Services);
18
+ protected doDocumentFormat(document: LangiumDocument, options: LSFormattingOptions, range?: Range): TextEdit[];
4
19
  protected format(node: AstNode): void;
5
20
  protected formatTags(node: AstNode): void;
6
21
  protected formatDeploymentRelation(node: AstNode): void;
22
+ protected formatExtendDeployment(node: AstNode): void;
7
23
  protected formatRelation(node: AstNode): void;
8
24
  protected removeIndentFromTopLevelStatements(node: AstNode): void;
9
25
  protected indentContentInBraces(node: AstNode): void;
@@ -15,7 +31,9 @@ export declare class LikeC4Formatter extends AbstractFormatter {
15
31
  protected formatAutolayoutProperty(node: AstNode): void;
16
32
  protected formatMetadataProperty(node: AstNode): void;
17
33
  protected formatElementDeclaration(node: AstNode): void;
34
+ protected formatExtendElement(node: AstNode): void;
18
35
  protected formatGlobals(node: AstNode): void;
36
+ protected formatImports(node: AstNode): void;
19
37
  protected formatSpecificationRule(node: AstNode): void;
20
38
  protected formatWithPredicate(node: AstNode): void;
21
39
  protected formatDeploymentNodeDeclaration(node: AstNode): void;
@@ -31,4 +49,10 @@ export declare class LikeC4Formatter extends AbstractFormatter {
31
49
  protected formatRelationExpression(node: AstNode): void;
32
50
  private findPredicateExpressionRoot;
33
51
  private on;
52
+ private doExtendedFormatting;
53
+ protected normalizeQuotes(node: AstNode): void;
54
+ private quotesNormalizerFactory;
55
+ private getAutoQuoteStyle;
56
+ private onConfigurationUpdate;
34
57
  }
58
+ export {};
@@ -1,4 +1,7 @@
1
- import { GrammarUtils } from "langium";
1
+ import { nonexhaustive } from "@likec4/core";
2
+ import {
3
+ GrammarUtils
4
+ } from "langium";
2
5
  import { AbstractFormatter, Formatting } from "langium/lsp";
3
6
  import { filter, isTruthy } from "remeda";
4
7
  import * as ast from "../generated/ast.js";
@@ -11,17 +14,37 @@ const FormattingOptions = {
11
14
  noIndent: Formatting.noIndent()
12
15
  };
13
16
  export class LikeC4Formatter extends AbstractFormatter {
17
+ options = {
18
+ quoteStyle: "auto"
19
+ };
20
+ extendedFormattingCommands = [];
21
+ constructor(services) {
22
+ super();
23
+ services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate(
24
+ (update) => this.onConfigurationUpdate(update.configuration.formatting)
25
+ );
26
+ }
27
+ doDocumentFormat(document, options, range) {
28
+ this.extendedFormattingCommands = [];
29
+ const edits = super.doDocumentFormat(document, options, range);
30
+ this.doExtendedFormatting(edits);
31
+ return edits;
32
+ }
14
33
  format(node) {
15
34
  this.removeIndentFromTopLevelStatements(node);
16
35
  this.indentContentInBraces(node);
36
+ this.normalizeQuotes(node);
37
+ this.formatImports(node);
17
38
  this.formatSpecificationRule(node);
18
39
  this.formatGlobals(node);
19
40
  this.formatElementDeclaration(node);
41
+ this.formatExtendElement(node);
20
42
  this.formatRelation(node);
21
43
  this.formatMetadataProperty(node);
22
44
  this.formatDeploymentNodeDeclaration(node);
23
45
  this.formatDeployedInstance(node);
24
46
  this.formatDeploymentRelation(node);
47
+ this.formatExtendDeployment(node);
25
48
  this.formatView(node);
26
49
  this.formatViewRuleGroup(node);
27
50
  this.formatViewRuleGlobalStyle(node);
@@ -41,7 +64,8 @@ export class LikeC4Formatter extends AbstractFormatter {
41
64
  }
42
65
  formatTags(node) {
43
66
  this.on(node, ast.isTags, (n, f) => {
44
- f.cst(GrammarUtils.findNodesForProperty(n.$cstNode, "values").slice(1)).prepend(FormattingOptions.oneSpace);
67
+ const tags = GrammarUtils.findNodesForProperty(n.$cstNode, "values").filter((x) => x).slice(1);
68
+ f.cst(tags).prepend(FormattingOptions.oneSpace);
45
69
  f.keywords(",").prepend(FormattingOptions.noSpace).append(FormattingOptions.oneSpace);
46
70
  });
47
71
  }
@@ -58,6 +82,11 @@ export class LikeC4Formatter extends AbstractFormatter {
58
82
  f.properties("title", "technology").prepend(FormattingOptions.oneSpace);
59
83
  });
60
84
  }
85
+ formatExtendDeployment(node) {
86
+ this.on(node, ast.isExtendDeployment, (n, f) => {
87
+ f.keywords("extend").append(FormattingOptions.oneSpace);
88
+ });
89
+ }
61
90
  formatRelation(node) {
62
91
  this.on(
63
92
  node,
@@ -76,8 +105,7 @@ export class LikeC4Formatter extends AbstractFormatter {
76
105
  );
77
106
  this.on(node, ast.isDynamicViewStep, (n, f) => {
78
107
  f.keywords("->", "<-").surround(FormattingOptions.oneSpace);
79
- const kind = f.property("kind");
80
- kind.nodes[0]?.text.startsWith(".") && kind.surround(FormattingOptions.oneSpace);
108
+ f.property("dotKind").prepend(FormattingOptions.oneSpace).append(FormattingOptions.oneSpace);
81
109
  f.keywords("]->").prepend(FormattingOptions.noSpace).append(FormattingOptions.oneSpace);
82
110
  f.keywords("-[").prepend(FormattingOptions.oneSpace).append(FormattingOptions.noSpace);
83
111
  f.properties("title").prepend(FormattingOptions.oneSpace);
@@ -90,7 +118,7 @@ export class LikeC4Formatter extends AbstractFormatter {
90
118
  }
91
119
  }
92
120
  indentContentInBraces(node) {
93
- if (ast.isLikeC4Lib(node) || ast.isSpecificationRule(node) || ast.isSpecificationElementKind(node) || ast.isSpecificationRelationshipKind(node) || ast.isSpecificationDeploymentNodeKind(node) || ast.isGlobals(node) || ast.isGlobalStyle(node) || ast.isGlobalStyleGroup(node) || ast.isGlobalPredicateGroup(node) || ast.isGlobalDynamicPredicateGroup(node) || ast.isGlobalStyleGroup(node) || ast.isModel(node) || ast.isElementBody(node) || ast.isExtendElementBody(node) || ast.isRelationBody(node) || ast.isRelationStyleProperty(node) || ast.isMetadataBody(node) || ast.isModelViews(node) || ast.isElementViewBody(node) || ast.isDynamicViewBody(node) || ast.isDeploymentViewBody(node) || ast.isViewRuleStyle(node) || ast.isViewRuleGroup(node) || ast.isCustomElementProperties(node) || ast.isCustomRelationProperties(node) || ast.isElementStyleProperty(node) || ast.isDynamicViewParallelSteps(node) || ast.isModelDeployments(node) || ast.isDeploymentNodeBody(node) || ast.isDeploymentRelationBody(node) || ast.isDeployedInstanceBody(node)) {
121
+ if (ast.isLikeC4Lib(node) || ast.isSpecificationRule(node) || ast.isSpecificationElementKind(node) || ast.isSpecificationRelationshipKind(node) || ast.isSpecificationDeploymentNodeKind(node) || ast.isGlobals(node) || ast.isGlobalStyle(node) || ast.isGlobalStyleGroup(node) || ast.isGlobalPredicateGroup(node) || ast.isGlobalDynamicPredicateGroup(node) || ast.isGlobalStyleGroup(node) || ast.isModel(node) || ast.isElementBody(node) || ast.isExtendElementBody(node) || ast.isRelationBody(node) || ast.isRelationStyleProperty(node) || ast.isMetadataBody(node) || ast.isModelViews(node) || ast.isElementViewBody(node) || ast.isDynamicViewBody(node) || ast.isDeploymentViewBody(node) || ast.isViewRuleStyle(node) || ast.isViewRuleGroup(node) || ast.isCustomElementProperties(node) || ast.isCustomRelationProperties(node) || ast.isElementStyleProperty(node) || ast.isDynamicViewParallelSteps(node) || ast.isModelDeployments(node) || ast.isDeploymentNodeBody(node) || ast.isDeploymentRelationBody(node) || ast.isDeployedInstanceBody(node) || ast.isExtendDeploymentBody(node)) {
94
122
  const formatter = this.getNodeFormatter(node);
95
123
  const openBrace = formatter.keywords("{");
96
124
  const closeBrace = formatter.keywords("}");
@@ -120,7 +148,7 @@ export class LikeC4Formatter extends AbstractFormatter {
120
148
  this.on(node, ast.isDeploymentView)?.keywords("deployment", "view").append(FormattingOptions.oneSpace);
121
149
  }
122
150
  formatLeafProperty(node) {
123
- if (ast.isElementStringProperty(node) || ast.isRelationStringProperty(node) || ast.isViewStringProperty(node) || ast.isNotationProperty(node) || ast.isSpecificationElementStringProperty(node) || ast.isSpecificationRelationshipStringProperty(node) || ast.isColorProperty(node) || ast.isLineProperty(node) || ast.isArrowProperty(node) || ast.isIconProperty(node) || ast.isShapeProperty(node) || ast.isBorderProperty(node) || ast.isOpacityProperty(node) || ast.isMultipleProperty(node) || ast.isShapeSizeProperty(node) || ast.isPaddingSizeProperty(node) || ast.isTextSizeProperty(node)) {
151
+ if (ast.isElementStringProperty(node) || ast.isRelationStringProperty(node) || ast.isViewStringProperty(node) || ast.isNotationProperty(node) || ast.isNotesProperty(node) || ast.isSpecificationElementStringProperty(node) || ast.isSpecificationRelationshipStringProperty(node) || ast.isColorProperty(node) || ast.isLineProperty(node) || ast.isArrowProperty(node) || ast.isIconProperty(node) || ast.isShapeProperty(node) || ast.isBorderProperty(node) || ast.isOpacityProperty(node) || ast.isMultipleProperty(node) || ast.isShapeSizeProperty(node) || ast.isPaddingSizeProperty(node) || ast.isTextSizeProperty(node)) {
124
152
  const formatter = this.getNodeFormatter(node);
125
153
  const colon = formatter.keyword(":");
126
154
  const propertyName = formatter.keywords(
@@ -128,6 +156,7 @@ export class LikeC4Formatter extends AbstractFormatter {
128
156
  "description",
129
157
  "technology",
130
158
  "notation",
159
+ "notes",
131
160
  "color",
132
161
  "line",
133
162
  "head",
@@ -189,6 +218,11 @@ export class LikeC4Formatter extends AbstractFormatter {
189
218
  f.properties("props").prepend(FormattingOptions.oneSpace);
190
219
  });
191
220
  }
221
+ formatExtendElement(node) {
222
+ this.on(node, ast.isExtendElement, (n, f) => {
223
+ f.keywords("extend").append(FormattingOptions.oneSpace);
224
+ });
225
+ }
192
226
  formatGlobals(node) {
193
227
  this.on(node, ast.isGlobalStyle, (n, f) => {
194
228
  f.keyword("style").append(FormattingOptions.oneSpace);
@@ -204,6 +238,15 @@ export class LikeC4Formatter extends AbstractFormatter {
204
238
  f.keyword("dynamicPredicateGroup").append(FormattingOptions.oneSpace);
205
239
  });
206
240
  }
241
+ formatImports(node) {
242
+ this.on(node, ast.isImportsFromPoject, (n, f) => {
243
+ f.keyword("import").append(FormattingOptions.oneSpace);
244
+ f.keywords("{", "}", "from").surround(FormattingOptions.oneSpace);
245
+ });
246
+ this.on(node, ast.isImported, (n, f) => {
247
+ f.keywords(",").prepend(FormattingOptions.noSpace).append(FormattingOptions.oneSpace);
248
+ });
249
+ }
207
250
  formatSpecificationRule(node) {
208
251
  if (ast.isSpecificationElementKind(node) || ast.isSpecificationRelationshipKind(node) || ast.isSpecificationTag(node) || ast.isSpecificationDeploymentNodeKind(node)) {
209
252
  const formatter = this.getNodeFormatter(node);
@@ -328,8 +371,7 @@ export class LikeC4Formatter extends AbstractFormatter {
328
371
  f.keywords("->", "<->").prepend(FormattingOptions.oneSpace);
329
372
  f.keywords("-[").prepend(FormattingOptions.oneSpace).append(FormattingOptions.noSpace);
330
373
  f.keywords("]->").prepend(FormattingOptions.noSpace).append(FormattingOptions.oneSpace);
331
- const kind = f.property("kind");
332
- kind.nodes[0]?.text.startsWith(".") && kind.surround(FormattingOptions.oneSpace);
374
+ f.property("dotKind").prepend(FormattingOptions.oneSpace).append(FormattingOptions.oneSpace);
333
375
  });
334
376
  this.on(node, ast.isDirectedRelationExpr, (n, f) => {
335
377
  f.property("target").prepend(FormattingOptions.oneSpace);
@@ -349,4 +391,60 @@ export class LikeC4Formatter extends AbstractFormatter {
349
391
  format && formatter && format(node, formatter);
350
392
  return formatter;
351
393
  }
394
+ doExtendedFormatting(edits) {
395
+ const quotesNormalizer = this.quotesNormalizerFactory(this.extendedFormattingCommands);
396
+ for (let command of this.extendedFormattingCommands) {
397
+ switch (command.type) {
398
+ case "normalizeQuotes":
399
+ quotesNormalizer(command, edits);
400
+ break;
401
+ default:
402
+ nonexhaustive(command.type);
403
+ }
404
+ }
405
+ }
406
+ normalizeQuotes(node) {
407
+ if (this.options.quoteStyle === "ignore") {
408
+ return;
409
+ }
410
+ let region = null;
411
+ region = region ?? this.on(node, ast.isStringProperty)?.property("value");
412
+ region = region ?? this.on(node, ast.isElement)?.properties("props");
413
+ region = region ?? this.on(node, ast.isImportsFromPoject)?.properties("project");
414
+ region = region ?? this.on(node, ast.isRelation)?.properties("title", "technology");
415
+ region = region ?? this.on(node, ast.isViewRuleGroup)?.properties("title");
416
+ region = region ?? this.on(node, ast.isDynamicViewStep)?.properties("title");
417
+ region = region ?? this.on(node, ast.isDeploymentNode)?.properties("title");
418
+ region = region ?? this.on(node, ast.isDeployedInstance)?.properties("title");
419
+ region = region ?? this.on(node, ast.isDeploymentRelation)?.properties("title", "technology");
420
+ region = region ?? this.on(node, ast.isLinkProperty)?.properties("title");
421
+ if (region) {
422
+ this.extendedFormattingCommands.push({ type: "normalizeQuotes", region });
423
+ }
424
+ }
425
+ quotesNormalizerFactory(commands) {
426
+ const quoteStyle = this.options.quoteStyle != "auto" ? this.options.quoteStyle : this.getAutoQuoteStyle(commands);
427
+ return (command, edits) => {
428
+ const quotesToReplace = quoteStyle === "single" ? '"' : "'";
429
+ const quotesToInsert = quoteStyle === "single" ? "'" : '"';
430
+ const newEdits = command.region.nodes.map((node) => ({
431
+ range: node.range,
432
+ newText: node.text.replaceAll(quotesToReplace, quotesToInsert)
433
+ }));
434
+ edits.push(...newEdits);
435
+ };
436
+ }
437
+ getAutoQuoteStyle(commands) {
438
+ const nodes = commands.flatMap((x) => x.region.nodes);
439
+ const doubleQuotesCount = nodes.filter((x) => x.text[0] == '"').length;
440
+ return doubleQuotesCount * 2 >= nodes.length ? "double" : "single";
441
+ }
442
+ onConfigurationUpdate(options) {
443
+ this.options = {
444
+ ...this.options,
445
+ ...options ?? {
446
+ quoteStyle: "auto"
447
+ }
448
+ };
449
+ }
352
450
  }