@cratis/screenplay-language 4.52.0 → 4.53.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 (190) hide show
  1. package/dist/TypeReferenceSymbol.d.ts +8 -0
  2. package/dist/TypeReferenceSymbol.d.ts.map +1 -0
  3. package/dist/bundles/chunk-7WJEZ72S.js +4463 -0
  4. package/dist/bundles/chunk-7WJEZ72S.js.map +7 -0
  5. package/dist/bundles/index.js +1410 -0
  6. package/dist/bundles/index.js.map +7 -0
  7. package/dist/bundles/sub-languages/capture/index.js +677 -0
  8. package/dist/bundles/sub-languages/capture/index.js.map +7 -0
  9. package/dist/bundles/sub-languages/projection/index.js +1647 -0
  10. package/dist/bundles/sub-languages/projection/index.js.map +7 -0
  11. package/dist/code-actions.d.ts +3 -0
  12. package/dist/code-actions.d.ts.map +1 -0
  13. package/dist/completion-items.d.ts +1 -0
  14. package/dist/completion-items.d.ts.map +1 -1
  15. package/dist/completion-planner.d.ts.map +1 -1
  16. package/dist/completions.d.ts.map +1 -1
  17. package/dist/diagnostic-codes.d.ts +3 -0
  18. package/dist/diagnostic-codes.d.ts.map +1 -1
  19. package/dist/diagnostics.d.ts.map +1 -1
  20. package/dist/hover-content.d.ts.map +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/keyword-docs.d.ts.map +1 -1
  24. package/dist/language.d.ts +1 -0
  25. package/dist/language.d.ts.map +1 -1
  26. package/dist/production-destinations.d.ts.map +1 -1
  27. package/dist/symbols.d.ts +4 -0
  28. package/dist/symbols.d.ts.map +1 -1
  29. package/dist/tokens.d.ts.map +1 -1
  30. package/dist/validation.d.ts +1 -0
  31. package/dist/validation.d.ts.map +1 -1
  32. package/package.json +13 -9
  33. package/DestinationHint.ts +0 -8
  34. package/ProductionSymbol.ts +0 -11
  35. package/completion-items.ts +0 -261
  36. package/completion-planner.ts +0 -167
  37. package/completions.ts +0 -156
  38. package/diagnostic-codes.ts +0 -43
  39. package/diagnostics.ts +0 -55
  40. package/dist/DestinationHint.js +0 -4
  41. package/dist/DestinationHint.js.map +0 -1
  42. package/dist/ProductionSymbol.js +0 -4
  43. package/dist/ProductionSymbol.js.map +0 -1
  44. package/dist/completion-items.js +0 -228
  45. package/dist/completion-items.js.map +0 -1
  46. package/dist/completion-planner.js +0 -143
  47. package/dist/completion-planner.js.map +0 -1
  48. package/dist/completions.js +0 -101
  49. package/dist/completions.js.map +0 -1
  50. package/dist/diagnostic-codes.js +0 -41
  51. package/dist/diagnostic-codes.js.map +0 -1
  52. package/dist/diagnostics.js +0 -50
  53. package/dist/diagnostics.js.map +0 -1
  54. package/dist/document-context.js +0 -85
  55. package/dist/document-context.js.map +0 -1
  56. package/dist/event-analysis-source.js +0 -19
  57. package/dist/event-analysis-source.js.map +0 -1
  58. package/dist/event-context-catalog.js +0 -116
  59. package/dist/event-context-catalog.js.map +0 -1
  60. package/dist/event-context.js +0 -88
  61. package/dist/event-context.js.map +0 -1
  62. package/dist/file-imports.js +0 -58
  63. package/dist/file-imports.js.map +0 -1
  64. package/dist/file-references.js +0 -70
  65. package/dist/file-references.js.map +0 -1
  66. package/dist/hover-content.js +0 -98
  67. package/dist/hover-content.js.map +0 -1
  68. package/dist/hover.js +0 -15
  69. package/dist/hover.js.map +0 -1
  70. package/dist/index.js +0 -61
  71. package/dist/index.js.map +0 -1
  72. package/dist/inlay-hints.js +0 -15
  73. package/dist/inlay-hints.js.map +0 -1
  74. package/dist/inline-event-validation.js +0 -131
  75. package/dist/inline-event-validation.js.map +0 -1
  76. package/dist/keyword-docs.js +0 -148
  77. package/dist/keyword-docs.js.map +0 -1
  78. package/dist/language.js +0 -196
  79. package/dist/language.js.map +0 -1
  80. package/dist/production-destinations.js +0 -32
  81. package/dist/production-destinations.js.map +0 -1
  82. package/dist/sub-language-registry.js +0 -18
  83. package/dist/sub-language-registry.js.map +0 -1
  84. package/dist/sub-languages/capture/CompletionProvider.js +0 -332
  85. package/dist/sub-languages/capture/CompletionProvider.js.map +0 -1
  86. package/dist/sub-languages/capture/HoverProvider.js +0 -87
  87. package/dist/sub-languages/capture/HoverProvider.js.map +0 -1
  88. package/dist/sub-languages/capture/Validator.js +0 -72
  89. package/dist/sub-languages/capture/Validator.js.map +0 -1
  90. package/dist/sub-languages/capture/index.js +0 -58
  91. package/dist/sub-languages/capture/index.js.map +0 -1
  92. package/dist/sub-languages/capture/language.js +0 -160
  93. package/dist/sub-languages/capture/language.js.map +0 -1
  94. package/dist/sub-languages/cdl.js +0 -74
  95. package/dist/sub-languages/cdl.js.map +0 -1
  96. package/dist/sub-languages/pdl.js +0 -73
  97. package/dist/sub-languages/pdl.js.map +0 -1
  98. package/dist/sub-languages/projection/CodeActionProvider.js +0 -93
  99. package/dist/sub-languages/projection/CodeActionProvider.js.map +0 -1
  100. package/dist/sub-languages/projection/CompletionProvider.js +0 -595
  101. package/dist/sub-languages/projection/CompletionProvider.js.map +0 -1
  102. package/dist/sub-languages/projection/HoverProvider.js +0 -333
  103. package/dist/sub-languages/projection/HoverProvider.js.map +0 -1
  104. package/dist/sub-languages/projection/Validator.js +0 -388
  105. package/dist/sub-languages/projection/Validator.js.map +0 -1
  106. package/dist/sub-languages/projection/index.js +0 -160
  107. package/dist/sub-languages/projection/index.js.map +0 -1
  108. package/dist/sub-languages/projection/language.js +0 -171
  109. package/dist/sub-languages/projection/language.js.map +0 -1
  110. package/dist/symbols.js +0 -275
  111. package/dist/symbols.js.map +0 -1
  112. package/dist/themes/screenplay-dark.js +0 -30
  113. package/dist/themes/screenplay-dark.js.map +0 -1
  114. package/dist/themes/screenplay-light.js +0 -30
  115. package/dist/themes/screenplay-light.js.map +0 -1
  116. package/dist/tokens.js +0 -147
  117. package/dist/tokens.js.map +0 -1
  118. package/dist/validation.js +0 -248
  119. package/dist/validation.js.map +0 -1
  120. package/document-context.ts +0 -93
  121. package/event-analysis-source.ts +0 -18
  122. package/event-context-catalog.ts +0 -135
  123. package/event-context.ts +0 -119
  124. package/file-imports.ts +0 -70
  125. package/file-references.ts +0 -87
  126. package/for_documentContext/when_stripping_comments.ts +0 -32
  127. package/for_eventContext/when_resolving_generated_catalog_vectors.ts +0 -15
  128. package/for_eventGenerations/when_editing_event_generations.ts +0 -57
  129. package/for_fileImports/when_finding_file_imports.ts +0 -38
  130. package/for_fileReferences/when_recognizing_an_absolute_path/with_paths_of_every_shape.ts +0 -26
  131. package/for_fileReferences/when_scanning_a_document/inside_a_code_fence.ts +0 -26
  132. package/for_fileReferences/when_scanning_a_document/with_a_bare_file_keyword.ts +0 -19
  133. package/for_fileReferences/when_scanning_a_document/with_a_file_directive.ts +0 -30
  134. package/for_fileReferences/when_scanning_a_document/with_a_property_named_file.ts +0 -25
  135. package/for_fileReferences/when_scanning_a_document/with_a_trailing_comment.ts +0 -25
  136. package/for_fileReferences/when_scanning_a_document/with_directives_on_several_constructs.ts +0 -41
  137. package/for_importablePaths/when_listing_what_a_document_can_import.ts +0 -34
  138. package/for_inlineEvents/when_analyzing_many_inline_events.ts +0 -59
  139. package/for_inlineEvents/when_authoring_inline_events.ts +0 -149
  140. package/for_inlineEvents/when_completing_many_events.ts +0 -49
  141. package/for_inlineEvents/when_indexing_command_production_ownership.ts +0 -79
  142. package/for_planCompletions/when_completing_a_file_import.ts +0 -26
  143. package/for_planCompletions/when_completing_a_specification_query.ts +0 -24
  144. package/for_planCompletions/when_completing_a_specification_step.ts +0 -42
  145. package/for_planCompletions/when_completing_an_absent_read_model.ts +0 -14
  146. package/for_planCompletions/when_completing_reaction_reads.ts +0 -36
  147. package/for_projectionCompletionProvider/when_completing_an_event_context_path.ts +0 -102
  148. package/for_projectionHoverProvider/when_hovering_an_event_context_path.ts +0 -44
  149. package/for_projectionValidator/when_validating_a_projection_with_variants.ts +0 -128
  150. package/for_projectionValidator/when_validating_event_context_paths.ts +0 -31
  151. package/for_scanDocument/when_scanning_a_query/with_a_dotted_return_type.ts +0 -34
  152. package/for_scanDocument/when_scanning_aliased_reads.ts +0 -33
  153. package/for_scanDocument/when_scanning_many_commands.ts +0 -47
  154. package/for_tokens/when_highlighting_a_file_import.ts +0 -18
  155. package/for_tokens/when_highlighting_event_metadata.ts +0 -63
  156. package/for_tokens/when_highlighting_specification_steps.ts +0 -28
  157. package/for_validateLines/when_validating_a_document/with_a_problem_of_every_coded_kind.ts +0 -77
  158. package/for_validateLines/when_validating_a_document/with_an_unknown_policy.ts +0 -33
  159. package/for_validateLines/when_validating_a_file_placed_by_an_import/with_names_declared_in_other_files.ts +0 -43
  160. package/for_validateLines/when_validating_event_context_paths/in_a_projection.ts +0 -97
  161. package/for_validateLines/when_validating_file_imports/at_every_level.ts +0 -36
  162. package/for_validateLines/when_validating_production_destinations/with_an_available_identifier.ts +0 -120
  163. package/hover-content.ts +0 -117
  164. package/hover.ts +0 -23
  165. package/index.ts +0 -125
  166. package/inlay-hints.ts +0 -17
  167. package/inline-event-validation.ts +0 -115
  168. package/keyword-docs.ts +0 -152
  169. package/language.ts +0 -212
  170. package/production-destinations.ts +0 -32
  171. package/sub-language-registry.ts +0 -42
  172. package/sub-languages/capture/CompletionProvider.ts +0 -365
  173. package/sub-languages/capture/HoverProvider.ts +0 -99
  174. package/sub-languages/capture/Validator.ts +0 -97
  175. package/sub-languages/capture/index.ts +0 -72
  176. package/sub-languages/capture/language.ts +0 -176
  177. package/sub-languages/cdl.ts +0 -76
  178. package/sub-languages/pdl.ts +0 -75
  179. package/sub-languages/projection/CodeActionProvider.ts +0 -123
  180. package/sub-languages/projection/CompletionProvider.ts +0 -660
  181. package/sub-languages/projection/HoverProvider.ts +0 -377
  182. package/sub-languages/projection/Validator.ts +0 -441
  183. package/sub-languages/projection/index.ts +0 -223
  184. package/sub-languages/projection/language.ts +0 -193
  185. package/symbols.ts +0 -374
  186. package/themes/screenplay-dark.ts +0 -33
  187. package/themes/screenplay-light.ts +0 -33
  188. package/tokens.ts +0 -174
  189. package/validation.ts +0 -443
  190. package/vitest.setup.ts +0 -5
@@ -1,261 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import { eventContextPaths } from './event-context';
5
-
6
- export interface CompletionEntry {
7
- label: string;
8
- insertText: string;
9
- documentation: string;
10
- }
11
-
12
- const fenced = (tag: string) => `\`\`\`${tag}\n\${1}\n\`\`\``;
13
-
14
- export const topLevelItems: CompletionEntry[] = [
15
- { label: 'import', insertText: 'import ${1:Module}.${2:Type}', documentation: 'Imports a type from another module by its qualified name.' },
16
- { label: 'import "…"', insertText: 'import "${1:**/*.play}"', documentation: 'Imports other `.play` files by path or glob, relative to this file\'s folder, as whole documents of the application.' },
17
- { label: 'concept', insertText: 'concept ${1:Name} : ${2|Uuid,String,Int,Decimal,Bool,Date,DateTime|}', documentation: 'Declares a formalized value type wrapping a primitive.' },
18
- { label: 'concept (enum)', insertText: 'concept ${1:Name} : Enum\n ${2:value}', documentation: 'Declares an enumeration concept with a fixed set of values.' },
19
- { label: 'concept (@pii with reason)', insertText: 'concept ${1:Name} : ${2|String,Uuid,Int,Decimal,Bool,Date,DateTime|} @pii\n pii reason "${3:why this is personal data, its purpose and lawful basis}"', documentation: 'Declares a personal-data concept together with the reason it is personal data.' },
20
- { label: 'type', insertText: 'type ${1:Name}\n ${2:property} ${3:Type}', documentation: 'Declares a composite value type — a named shape built from several properties.' },
21
- { label: 'policy', insertText: 'policy ${1:Name}\n require ${2:authenticated}', documentation: 'Declares a named authorization rule for commands and queries.' },
22
- { label: 'module', insertText: 'module ${1:Name}\n ', documentation: 'Declares the top-level namespace — maps to a bounded context.' },
23
- ];
24
-
25
- export const conceptItems: CompletionEntry[] = [
26
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Names the repository relative file this declaration is realized by, so the document can be navigated back to the code.' },
27
- { label: 'pii reason', insertText: 'pii reason "${1:why this is personal data, its purpose and lawful basis}"', documentation: 'Records why the `@pii` marker applies — purpose, lawful basis, whose subject it lives under.' },
28
- { label: 'sensitive reason', insertText: 'sensitive reason "${1:why this value is sensitive}"', documentation: 'Records why the `@sensitive` marker applies.' },
29
- { label: 'validate', insertText: 'validate\n ${1:not empty} message "${2:message}"', documentation: 'Validation rules that travel with the value everywhere it appears.' },
30
- ];
31
-
32
- export const typeItems: CompletionEntry[] = [
33
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Names the repository relative file this declaration is realized by, so the document can be navigated back to the code.' },
34
- { label: 'description', insertText: 'description "${1:what this shape represents}"', documentation: 'A human-readable description of the type.' },
35
- { label: 'property', insertText: '${1:property} ${2:Type}', documentation: 'A property of the type — a name and a type reference.' },
36
- ];
37
-
38
- export const moduleItems: CompletionEntry[] = [
39
- { label: 'import "…"', insertText: 'import "${1:*/*.play}"', documentation: 'Imports `.play` files into this module — their top level is the module\'s body, so they hold features and module members without restating the module.' },
40
- { label: 'layout', insertText: 'layout ${1:Name}\n template\n ${2:slot}', documentation: 'Declares a reusable screen template with named slots.' },
41
- { label: 'feature', insertText: 'feature ${1:Name}\n ', documentation: 'Groups related slices into a vertical feature.' },
42
- ];
43
-
44
- export const featureItems: CompletionEntry[] = [
45
- { label: 'import "…"', insertText: 'import "${1:*.play}"', documentation: 'Imports `.play` files into this feature — their top level is the feature\'s body, so they hold slices and nested features without restating where they belong.' },
46
- { label: 'feature', insertText: 'feature ${1:Name}\n ', documentation: 'Declares a nested sub-feature.' },
47
- { label: 'slice StateChange', insertText: 'slice StateChange ${1:Name}\n ', documentation: 'A command → events flow; something that changes the system.' },
48
- { label: 'slice StateView', insertText: 'slice StateView ${1:Name}\n ', documentation: 'A query + projection + screen; something that reads the system.' },
49
- { label: 'slice Automation', insertText: 'slice Automation ${1:Name}\n ', documentation: 'A reaction or reducer; something that runs when something happens.' },
50
- { label: 'slice Translate', insertText: 'slice Translate ${1:Name}\n ', documentation: 'A capture; converts external data into events.' },
51
- ];
52
-
53
- export const sliceItems: CompletionEntry[] = [
54
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Names the repository relative file this declaration is realized by, so the document can be navigated back to the code.' },
55
- { label: 'event', insertText: 'event ${1:Name}\n ${2:property} ${3:Type}', documentation: 'Declares an event type — an immutable, past-tense fact.' },
56
- { label: 'event generation', insertText: 'event ${1:Name} generation ${2:2}\n ${3:property} ${4:Type}', documentation: 'Declares a complete numbered event generation; start at 1 and do not skip a number.' },
57
- { label: 'command', insertText: 'command ${1:Name}\n ${2:property} ${3:Type}', documentation: 'Declares a command — an imperative intent that produces events.' },
58
- { label: 'query', insertText: 'query ${1:Name} => ${2:ReadModel}', documentation: 'Declares a read-side entry point mapping to a return type.' },
59
- { label: 'query observable', insertText: 'query ${1:Name} => observable ${2:ReadModel}', documentation: 'Declares a live read — the query keeps pushing as the read model changes, instead of answering once.' },
60
- { label: 'projection', insertText: 'projection ${1:Name} => ${2:ReadModel}\n from ${3:EventType}', documentation: 'Declares how events project into a read model (PDL).' },
61
- { label: 'capture', insertText: 'capture ${1:Name}\n source ${2:api}', documentation: 'Declares a change data capture converting external data into events (CDL).' },
62
- { label: 'reaction', insertText: 'reaction ${1:Name}\n when ${2:Trigger}', documentation: 'Declares behavior that runs when something happens.' },
63
- { label: 'screen', insertText: 'screen ${1:Name}\n data ${2:ReadModel} via query ${3:QueryName}', documentation: 'Declares a UI screen.' },
64
- { label: 'constraint', insertText: 'constraint ${1:Name}\n unique ${2:property} on ${3:EventType}', documentation: 'Declares a server-side rule enforced before events are committed.' },
65
- ];
66
-
67
- export const commandItems: CompletionEntry[] = [
68
- { label: 'produces event', insertText: 'produces event ${1:Name}\n ${2:property} ${3:Type} = ${4:source}', documentation: 'Declares a slice-owned generation-1 event and maps its properties. An omitted for uses the command identifier.' },
69
- { label: 'identifier property', insertText: '${1:property} ${2:Type} identifier', documentation: 'Marks the property a runtime resolves the event source id from. At most one per command.' },
70
- { label: 'authorize', insertText: 'authorize ${1:PolicyName}', documentation: 'References the policies that must pass for the command to execute.' },
71
- { label: 'reads', insertText: 'reads ${1:View} by ${2:property}', documentation: 'Declares a view the command consults. Executable binding is not yet supported.' },
72
- { label: 'reads as', insertText: 'reads ${1:View} as ${2:alias} by ${3:property}', documentation: 'Names one instance of a view; every instance needs a unique alias when reading the same view more than once.' },
73
- { label: 'validate', insertText: 'validate\n ${1:property} not empty message "${2:message}"', documentation: 'Declarative validation rules with messages.' },
74
- { label: 'validate csharp', insertText: `validate\n ${fenced('csharp')}`, documentation: 'Imperative validation in C#, yielding the message of every rule the artifact breaks.' },
75
- { label: 'produces', insertText: 'produces ${1:EventType}\n ${2:property} = ${3:source}', documentation: 'Declares the event the command emits, with property mappings.' },
76
- { label: 'produces when', insertText: 'produces when ${1:condition}\n ${2:EventType}\n ${3:property} = ${4:source}', documentation: 'Conditionally emits an event when the condition holds.' },
77
- { label: 'handler', insertText: 'handler\n ', documentation: 'Fully imperative command implementation — file reference or inline C#, instead of produces.' },
78
- ];
79
-
80
- export const eventItems: CompletionEntry[] = [
81
- { label: 'description', insertText: 'description "${1:what happened}"', documentation: 'Authoring metadata, as one line or a text/markdown fence.' },
82
- { label: 'documentation', insertText: 'documentation\n ```markdown\n ${1:Details}\n ```', documentation: 'Authoring-only Markdown documentation.' },
83
- { label: 'id', insertText: 'id "${1:OldName}"', documentation: 'Preserves a previous persisted event name after a rename. Leave absent for new events.' },
84
- { label: 'tag', insertText: 'tag ${1:audit}', documentation: 'An event-type tag stamped on every occurrence.' },
85
- ];
86
-
87
- export const inlineEventItems: CompletionEntry[] = [
88
- ...eventItems,
89
- { label: 'for', insertText: 'for ${1:identifier}', documentation: 'Explicitly names the command identifier used as the event source.' },
90
- { label: 'property mapping', insertText: '${1:property} ${2:Type} = ${3:source}', documentation: 'Declares and maps an event property on one line.' },
91
- ];
92
-
93
- export const producesItems: CompletionEntry[] = [
94
- { label: 'when', insertText: 'when ${1:condition}', documentation: 'Guards the produced event with a condition.' },
95
- ];
96
-
97
- export const handlerItems: CompletionEntry[] = [
98
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Delegates the command implementation to an external C# file.' },
99
- { label: 'csharp', insertText: fenced('csharp'), documentation: 'Inline C# returning the events to append.' },
100
- ];
101
-
102
- export const queryItems: CompletionEntry[] = [
103
- { label: 'description', insertText: 'description "${1:what this query is trying to accomplish}"', documentation: 'What the query is for, in prose — what a generator or reviewer works from.' },
104
- { label: 'by', insertText: 'by ${1:param} ${2:Type}', documentation: 'Declares the identifying parameter of the query.' },
105
- { label: 'filter', insertText: 'filter ${1:param} ${2:Type}?', documentation: 'Declares an optional filter parameter supplied by the caller.' },
106
- { label: 'filter from context', insertText: 'filter ${1:param} ${2:Type} from $context.${3|tenant,causedBy.subject,occurred|}', documentation: 'Declares a parameter filled from the query context instead of the caller.' },
107
- { label: 'authorize', insertText: 'authorize ${1:PolicyName}', documentation: 'References the policies that must pass for the query to execute.' },
108
- { label: 'performer', insertText: 'performer\n ', documentation: 'The code that performs the query — a file reference or an inline csharp/sql block.' },
109
- ];
110
-
111
- export const performerItems: CompletionEntry[] = [
112
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Delegates the query implementation to an external file.' },
113
- { label: 'csharp', insertText: fenced('csharp'), documentation: 'Inline C# returning the query result, with the QueryContext in scope as context.' },
114
- { label: 'sql', insertText: fenced('sql'), documentation: 'Inline SQL returning the query result.' },
115
- ];
116
-
117
- export const constraintItems: CompletionEntry[] = [
118
- { label: 'unique', insertText: 'unique ${1:property} on ${2:EventType}', documentation: 'Enforces a unique property value across an event type.' },
119
- { label: 'unique event', insertText: 'unique event ${1:EventType}', documentation: 'Enforces that the event type occurs at most once per event source.' },
120
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Delegates the constraint to a custom C# implementation.' },
121
- ];
122
-
123
- export const reactionItems: CompletionEntry[] = [
124
- { label: 'description', insertText: 'description "${1:what this reaction does}"', documentation: 'What the reaction does — a complete statement of intent before any code exists.' },
125
- { label: 'when', insertText: 'when ${1:Trigger}', documentation: 'An event, a declared trigger or a host signal that sets the reaction off. A trigger needs no body.' },
126
- { label: 'every', insertText: 'every ${1:15} ${2|seconds,minutes,hours,days|}', documentation: 'Runs the reaction on an interval.' },
127
- { label: 'at', insertText: 'at ${1:08:00}', documentation: 'Runs the reaction at a time of day — every day unless narrowed with `on <Weekday>` or `on day <n>`.' },
128
- { label: 'where', insertText: 'where ${1:condition}', documentation: 'Narrows which occurrences actually run the reaction.' },
129
- ];
130
-
131
- export const reactionTriggerItems: CompletionEntry[] = [
132
- { label: 'reads', insertText: 'reads ${1:View}', documentation: 'The view this trigger consults. Optionally use `as <alias> by <trigger value>`; clock triggers take no values and cannot use `by`.' },
133
- { label: 'description', insertText: 'description "${1:what this reaction does}"', documentation: 'What this particular reaction does — enough on its own, with no file to point at.' },
134
- { label: 'produces', insertText: 'produces ${1:EventType}', documentation: 'An event the reaction appends.' },
135
- { label: 'invokes', insertText: 'invokes ${1:Command}', documentation: 'A command the reaction hands on. A command is asked for, not produced — it may still be rejected.' },
136
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Delegates the reaction to an external C# file.' },
137
- { label: 'csharp', insertText: fenced('csharp'), documentation: 'Inline C# returning event side effects.' },
138
- ];
139
-
140
- export const triggerItems: CompletionEntry[] = [
141
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Names the repository relative file this declaration is realized by, so the document can be navigated back to the code.' },
142
- { label: 'description', insertText: 'description "${1:when this occurs}"', documentation: 'What makes an occurrence of this trigger happen.' },
143
- { label: 'value', insertText: '${1:name} ${2:Type}', documentation: 'A value an occurrence hands the reaction. The type is optional.' },
144
- ];
145
-
146
- export const specificationItems: CompletionEntry[] = [
147
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Names the repository relative file this declaration is realized by, so the document can be navigated back to the code.' },
148
- { label: 'given', insertText: 'given ${1:EventType}\n ${2:property} = ${3:value}', documentation: 'Establishes prior state by replaying an event before the command runs.' },
149
- { label: 'given readmodel', insertText: 'given readmodel ${1:ReadModelType}\n ${2:property} = ${3:value}', documentation: 'Establishes prior read model state directly.' },
150
- { label: 'when', insertText: 'when ${1:CommandType}\n ${2:property} = ${3:value}', documentation: 'The command being exercised.' },
151
- { label: 'then', insertText: 'then ${1:EventType}\n ${2:property} = ${3:value}', documentation: 'An event expected to be produced by the command.' },
152
- { label: 'then readmodel', insertText: 'then readmodel ${1:ReadModelType}\n ${2:property} = ${3:value}', documentation: 'The read model state expected after the command.' },
153
- { label: 'then no readmodel', insertText: 'then no readmodel ${1:ReadModelType} for ${2:key}', documentation: 'Asserts that precisely one keyed read-model instance does not exist; another key may still be present.' },
154
- { label: 'then query', insertText: 'then query ${1:QueryName}\n arguments\n ${2:argument} = ${3:value}\n result\n ${4:property} = ${5:value}', documentation: 'The ordered query results expected for explicit arguments. Remove the result block to assert an empty result.' },
155
- { label: 'then error', insertText: 'then error', documentation: 'A rejection, for a reason this specification does not name.' },
156
- { label: 'then error "..."', insertText: 'then error "${1:reason}"', documentation: 'A rejection, for the named reason.' },
157
- { label: 'given clock', insertText: 'given clock "${1:2026-10-05T08:00:00Z}"', documentation: 'The instant the scenario happens at - the occurrence time of everything it does. At most once.' },
158
- { label: 'given capture', insertText: 'given capture ${1:Capture}\n ${2:field} = ${3:value}', documentation: 'A record the capture\'s source held before.' },
159
- { label: 'when clock', insertText: 'when clock "${1:2026-10-05T09:00:00Z}"', documentation: 'The clock reaches an instant, as the action.' },
160
- { label: 'when trigger', insertText: 'when trigger ${1:Trigger}\n ${2:value} = ${3:value}', documentation: 'An application trigger fires, as the action.' },
161
- { label: 'when capture', insertText: 'when capture ${1:Capture}\n ${2:field} = ${3:value}', documentation: 'The record a capture\'s source holds now, as the action.' },
162
- { label: 'when query', insertText: 'when query ${1:Query}\n ${2:argument} = ${3:value}', documentation: 'Performs a query, as the action.' },
163
- { label: 'then result', insertText: 'then result\n ${1:property} = ${2:value}', documentation: 'One result the query performed by `when query` returns, in order.' },
164
- { label: 'then no result', insertText: 'then no result', documentation: 'The query performed by `when query` returns nothing.' },
165
- ];
166
-
167
- // What follows a 'given', 'when' or 'then' already typed in a specification.
168
- export const specificationStepItems: Record<'given' | 'when' | 'then', CompletionEntry[]> = {
169
- given: [
170
- { label: 'clock', insertText: 'clock "${1:2026-10-05T08:00:00Z}"', documentation: 'The instant the scenario happens at - the occurrence time of everything it does.' },
171
- { label: 'capture', insertText: 'capture ${1:Capture}\n ${2:field} = ${3:value}', documentation: 'A record the capture\'s source held before. Repeat it for several records.' },
172
- { label: 'readmodel', insertText: 'readmodel ${1:ReadModelType}\n ${2:property} = ${3:value}', documentation: 'Establishes prior read model state directly.' },
173
- { label: 'caller', insertText: 'caller\n ${1:authenticated}', documentation: 'The identity the scenario runs as.' },
174
- ],
175
- when: [
176
- { label: 'clock', insertText: 'clock "${1:2026-10-05T09:00:00Z}"', documentation: 'The clock reaches an instant - what a scheduled reaction responds to.' },
177
- { label: 'trigger', insertText: 'trigger ${1:Trigger}\n ${2:value} = ${3:value}', documentation: 'An application trigger fires, with the values it carries.' },
178
- { label: 'capture', insertText: 'capture ${1:Capture}\n ${2:field} = ${3:value}', documentation: 'The record a capture\'s source holds now.' },
179
- { label: 'query', insertText: 'query ${1:Query}\n ${2:argument} = ${3:value}', documentation: 'Performs a query; assert what it returns with `then result` or `then no result`.' },
180
- { label: 'append', insertText: 'append ${1:EventType}\n ${2:property} = ${3:value}', documentation: 'An event occurs, instead of a command being executed.' },
181
- ],
182
- then: [
183
- { label: 'result', insertText: 'result\n ${1:property} = ${2:value}', documentation: 'One result the query performed by `when query` returns, in order.' },
184
- { label: 'result exactly', insertText: 'result exactly\n ${1:property} = ${2:value}', documentation: 'One result, with every property asserted.' },
185
- { label: 'no result', insertText: 'no result', documentation: 'The query performed by `when query` returns nothing.' },
186
- { label: 'readmodel', insertText: 'readmodel ${1:ReadModelType}\n ${2:property} = ${3:value}', documentation: 'The read model state expected afterwards.' },
187
- { label: 'error', insertText: 'error "${1:reason}"', documentation: 'A rejection, for the named reason.' },
188
- { label: 'denied', insertText: 'denied', documentation: 'The action is denied to the caller.' },
189
- ],
190
- };
191
-
192
- export const ruleItems: CompletionEntry[] = [
193
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Gives the named predicate its implementation in an external C# file.' },
194
- { label: 'csharp', insertText: fenced('csharp'), documentation: 'Gives the named predicate its implementation as inline C# returning a bool.' },
195
- ];
196
-
197
- export const policyItems: CompletionEntry[] = [
198
- { label: 'require authenticated', insertText: 'require authenticated', documentation: 'Requires an authenticated caller.' },
199
- { label: 'require role', insertText: 'require role "${1:role}"', documentation: 'Requires the caller to have a role.' },
200
- { label: 'require claim', insertText: 'require claim "${1:claim}" matches ${2:subject}', documentation: 'Requires a claim to match the subject or a value.' },
201
- { label: 'csharp', insertText: fenced('csharp'), documentation: 'Fully custom policy logic in C#, returning a bool.' },
202
- ];
203
-
204
- export const validateItems: CompletionEntry[] = [
205
- { label: 'not empty', insertText: '${1:property} not empty message "${2:message}"', documentation: 'The property must have a value.' },
206
- { label: 'max', insertText: '${1:property} max ${2:500} message "${3:message}"', documentation: 'Maximum length or value.' },
207
- { label: 'min', insertText: '${1:property} min ${2:1} message "${3:message}"', documentation: 'Minimum length or value.' },
208
- { label: 'matches', insertText: '${1:property} matches "${2:pattern}" message "${3:message}"', documentation: 'The property must match a regular expression.' },
209
- { label: 'rule', insertText: '${1:property} rule ${2:PredicateName} message "${3:message}"', documentation: 'Names a predicate — optionally followed by an indented `file` reference or inline `csharp` block giving it a body; bare, it just states that a constraint exists.' },
210
- { label: '==', insertText: '${1:property} == ${2:value} message "${3:message}"', documentation: 'The property must equal the value.' },
211
- { label: '!=', insertText: '${1:property} != ${2:value} message "${3:message}"', documentation: 'The property must not equal the value.' },
212
- { label: 'length ==', insertText: '${1:property} length == ${2:3} message "${3:message}"', documentation: 'The property must have an exact length.' },
213
- { label: 'all >', insertText: '${1:collection}.${2:property} all > ${3:0} message "${4:message}"', documentation: 'Every element of a collection must satisfy the comparison.' },
214
- ];
215
-
216
- export const screenItems: CompletionEntry[] = [
217
- { label: 'data', insertText: 'data ${1:ReadModel} via query ${2:QueryName}', documentation: 'Binds a read model to the screen through a query.' },
218
- { label: 'action', insertText: 'action ${1:CommandName}', documentation: 'Makes a command available as an action on the screen.' },
219
- { label: 'layout', insertText: 'layout ${1:LayoutName}', documentation: 'Uses a layout template and fills its slots.' },
220
- { label: 'section', insertText: 'section ${1:name}', documentation: 'A named structural section of the screen.' },
221
- { label: 'table', insertText: 'table ${1:name}\n column ${2:property} label "${3:text}"', documentation: 'A table widget over a read model or collection.' },
222
- { label: 'summary', insertText: 'summary ${1:ReadModel}\n field ${2:property} label "${3:text}"', documentation: 'A summary widget showing labeled fields.' },
223
- { label: 'title', insertText: 'title "${1:text}"', documentation: 'The title of the screen or section.' },
224
- { label: 'file', insertText: 'file ${1:Path}', documentation: 'Full external implementation — Stage uses the referenced file.' },
225
- { label: 'react', insertText: fenced('react'), documentation: 'Inline React/TSX component receiving the data contract as Props.' },
226
- { label: 'typescript', insertText: fenced('typescript'), documentation: 'Inline plain TypeScript.' },
227
- { label: 'html', insertText: fenced('html'), documentation: 'Inline static HTML.' },
228
- ];
229
-
230
- export const actionItems: CompletionEntry[] = [
231
- { label: 'navigate to', insertText: 'navigate to ${1:ScreenName}', documentation: 'Navigates to a screen after the action completes.' },
232
- { label: 'label', insertText: 'label "${1:text}"', documentation: 'The display label of the action.' },
233
- ];
234
-
235
- export const tableItems: CompletionEntry[] = [
236
- { label: 'column', insertText: 'column ${1:property} label "${2:text}"', documentation: 'A column bound to a property.' },
237
- { label: 'on row-click', insertText: 'on row-click navigate to ${1:ScreenName} by ${2:param}', documentation: 'Navigates when a row is clicked.' },
238
- ];
239
-
240
- export const contextVariableItems: CompletionEntry[] = [
241
- { label: '$context.occurred', insertText: '$context.occurred', documentation: 'When the command or query was received.' },
242
- { label: '$context.tenant', insertText: '$context.tenant', documentation: 'The tenant the command or query is executing for.' },
243
- { label: '$context.command.', insertText: '$context.command.${1:property}', documentation: 'A property of the command being handled.' },
244
- { label: '$context.arguments.', insertText: '$context.arguments.${1:name}', documentation: 'An argument of the query being performed.' },
245
- { label: '$context.causedBy.subject', insertText: '$context.causedBy.subject', documentation: 'Subject of the identity that caused the command or query.' },
246
- { label: '$context.causedBy.name', insertText: '$context.causedBy.name', documentation: 'Display name of the identity that caused the command or query.' },
247
- { label: '$context.causedBy.userName', insertText: '$context.causedBy.userName', documentation: 'User name of the identity that caused the command or query.' },
248
- { label: '$context.causation.type', insertText: '$context.causation.type', documentation: 'What caused this — a command, a reactor, a schedule.' },
249
- { label: '$context.identity.id', insertText: '$context.identity.id', documentation: 'The identifier of the caller from the auth token.' },
250
- { label: '$context.identity.name', insertText: '$context.identity.name', documentation: 'The display name of the caller.' },
251
- { label: '$context.identity.userName', insertText: '$context.identity.userName', documentation: 'The user name of the caller.' },
252
- { label: '$context.identity.isAuthenticated', insertText: '$context.identity.isAuthenticated', documentation: 'Whether the caller is authenticated.' },
253
- { label: '$context.identity.roles', insertText: '$context.identity.roles', documentation: 'The roles the caller holds.' },
254
- { label: '$context.identity.claims.', insertText: '$context.identity.claims.${1:name}', documentation: 'The value of a claim the caller carries.' },
255
- { label: '$env.', insertText: '$env.${1:VAR_NAME}', documentation: 'An environment variable.' },
256
- // Every $eventContext path the event-context catalog lists, for projections - the underlying value of a concept
257
- // is left out, it reads the same as the member it belongs to.
258
- ...eventContextPaths
259
- .filter((path) => path.name !== 'value')
260
- .map((path) => ({ label: `$eventContext.${path.path}`, insertText: `$eventContext.${path.path}`, documentation: `${path.description} (PDL)` })),
261
- ];
@@ -1,167 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import { enclosingChain, fenceMap, indentOf, nearestEnclosingLine } from './document-context';
5
- import { getSubLanguage } from './sub-language-registry';
6
- import * as items from './completion-items';
7
- import { CompletionEntry } from './completion-items';
8
-
9
- // Matches a validation rule line ending in "rule <Name>" (optionally followed by a
10
- // message clause) - both the command form ("<property> rule <Name>") and the
11
- // concept implied-subject form ("rule <Name>"). Its first word is the property
12
- // name, not "rule", so it can't be recognized through the chain[0] keyword switch
13
- // the way "on <EventType>" or "handler" are - hence the dedicated regex check.
14
- const RULE_LINE_PATTERN = /(?:^|\s)rule\s+[A-Za-z_]\w*(?:\s+message\s+.*)?$/;
15
-
16
- export type CompletionPlan =
17
- | { kind: 'none' }
18
- | { kind: 'entries'; entries: CompletionEntry[] }
19
- | { kind: 'contextVariables'; replaceLength: number }
20
- | { kind: 'playFiles'; replaceLength: number }
21
- | { kind: 'policies' }
22
- | { kind: 'events' }
23
- | { kind: 'triggers' }
24
- | { kind: 'commands' }
25
- | { kind: 'producesTargets' }
26
- | { kind: 'screens' }
27
- | { kind: 'queries' }
28
- | { kind: 'types' };
29
-
30
- export function completionEntriesFor(chain: string[]): CompletionEntry[] {
31
- const construct = chain[0];
32
- if (construct === undefined) return items.topLevelItems;
33
- const subLanguage = getSubLanguage(construct);
34
- if (subLanguage) return subLanguage.completions ?? [];
35
- switch (construct) {
36
- case 'module':
37
- return items.moduleItems;
38
- case 'feature':
39
- return items.featureItems;
40
- case 'slice':
41
- return items.sliceItems;
42
- case 'concept':
43
- return items.conceptItems;
44
- case 'type':
45
- return items.typeItems;
46
- case 'command':
47
- return items.commandItems;
48
- case 'event':
49
- return items.eventItems;
50
- case 'produces':
51
- return items.producesItems;
52
- case 'handler':
53
- return items.handlerItems;
54
- case 'query':
55
- return items.queryItems;
56
- case 'performer':
57
- return items.performerItems;
58
- case 'constraint':
59
- return items.constraintItems;
60
- case 'reaction':
61
- return items.reactionItems;
62
- case 'trigger':
63
- return items.triggerItems;
64
- case 'when':
65
- case 'every':
66
- case 'at':
67
- return chain.includes('reaction') ? items.reactionTriggerItems : [];
68
- case 'specification':
69
- return items.specificationItems;
70
- case 'policy':
71
- return items.policyItems;
72
- case 'validate':
73
- return items.validateItems;
74
- case 'action':
75
- return items.actionItems;
76
- case 'table':
77
- case 'summary':
78
- return items.tableItems;
79
- default:
80
- // Layout slots and sections inside a screen expose the screen vocabulary.
81
- if (chain.includes('screen') || construct === 'section' || construct === 'layout') {
82
- return items.screenItems;
83
- }
84
- if (chain.includes('produces')) return items.producesItems;
85
- return [];
86
- }
87
- }
88
-
89
- // Decides what to complete at a position, without any editor dependency — the
90
- // Monaco service and the VSCode extension both materialize the plan into items.
91
- export function planCompletions(
92
- lines: string[],
93
- lineIndex: number,
94
- textBefore: string,
95
- ): CompletionPlan {
96
- const fences = fenceMap(lines);
97
- if (fences[lineIndex]) return { kind: 'none' };
98
-
99
- // Inside the quotes of a file import, what is wanted is a path - replacing what has been typed so far.
100
- const importPath = textBefore.match(/^\s*import\s+"([^"]*)$/);
101
- if (importPath) {
102
- return { kind: 'playFiles', replaceLength: importPath[1].length };
103
- }
104
-
105
- // A quote or a slash only asks for a completion inside an import path.
106
- if (/["/]$/.test(textBefore)) return { kind: 'none' };
107
-
108
- const contextVariableMatch = textBefore.match(/\$[\w.]*$/);
109
- if (contextVariableMatch) {
110
- return { kind: 'contextVariables', replaceLength: contextVariableMatch[0].length };
111
- }
112
-
113
- const currentLine = lines[lineIndex] ?? '';
114
- const effectiveIndent =
115
- textBefore.trim().length === 0 ? textBefore.length : indentOf(currentLine);
116
- const chain = enclosingChain(lines, fences, lineIndex, effectiveIndent);
117
-
118
- if (/\bauthorize\s+[\w\s]*$/.test(textBefore) || chain[0] === 'authorize') {
119
- return { kind: 'policies' };
120
- }
121
- if (/\bwhen\s+\w*$/.test(textBefore) && chain.includes('reaction')) {
122
- return { kind: 'triggers' };
123
- }
124
- if (/\bon\s+\w*$/.test(textBefore) && chain.includes('constraint')) {
125
- return { kind: 'events' };
126
- }
127
- if (/\binvokes\s+\w*$/.test(textBefore) && chain.includes('reaction')) {
128
- return { kind: 'commands' };
129
- }
130
- if (/\b(?:on|unique\s+event)\s+\w*$/.test(textBefore) && chain[0] === 'constraint') {
131
- return { kind: 'events' };
132
- }
133
- if (/\bproduces\s+\w*$/.test(textBefore)) {
134
- return { kind: 'producesTargets' };
135
- }
136
- if (/\bnavigate\s+to\s+\w*$/.test(textBefore)) {
137
- return { kind: 'screens' };
138
- }
139
- if (chain[0] === 'specification') {
140
- if (/^\s*when\s+query\s+[\w.]*$/.test(textBefore)) return { kind: 'queries' };
141
- const step = textBefore.match(/^\s*(given|when|then)\s+\w*$/);
142
- if (step) return { kind: 'entries', entries: items.specificationStepItems[step[1] as 'given' | 'when' | 'then'] };
143
- }
144
- if (/\b(?:via|then)\s+query\s+[\w.]*$/.test(textBefore)) {
145
- return { kind: 'queries' };
146
- }
147
- if (
148
- (chain[0] === 'event' || chain[0] === 'command' || chain[0] === 'type') &&
149
- /^\s+[a-z_]\w*\s+[\w[\]?]*$/.test(textBefore)
150
- ) {
151
- return { kind: 'types' };
152
- }
153
- if (chain[0] === 'query' && /^\s+(?:by|filter)\s+[a-z_]\w*\s+[\w[\]?]*$/.test(textBefore)) {
154
- return { kind: 'types' };
155
- }
156
-
157
- const enclosingLine = nearestEnclosingLine(lines, fences, lineIndex, effectiveIndent);
158
- if (enclosingLine && /^produces\s+event\b/.test(enclosingLine)) {
159
- if (/^\s+@?[a-z_]\w*\s+[\w[\]?]*$/.test(textBefore)) return { kind: 'types' };
160
- return { kind: 'entries', entries: items.inlineEventItems };
161
- }
162
- if (enclosingLine && RULE_LINE_PATTERN.test(enclosingLine)) {
163
- return { kind: 'entries', entries: items.ruleItems };
164
- }
165
-
166
- return { kind: 'entries', entries: completionEntriesFor(chain) };
167
- }
package/completions.ts DELETED
@@ -1,156 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import type { editor, languages } from 'monaco-editor';
5
- import { Monaco, primitiveTypes } from './language';
6
- import { knownEventNames, knownTriggerNames, scanDocument } from './symbols';
7
- import { planCompletions } from './completion-planner';
8
- import { contextVariableItems, producesItems, CompletionEntry } from './completion-items';
9
-
10
- // What a host knows beyond the one model the editor holds.
11
- export interface CompletionOptions {
12
- // The paths a file import written in the model can name, relative to the model's folder - typically
13
- // importablePaths over the host's .play files. Without it, an import path is not completed.
14
- playFiles?: (model: editor.ITextModel) => readonly string[];
15
- }
16
-
17
- export function createCompletionProvider(monaco: Monaco, options: CompletionOptions = {}): languages.CompletionItemProvider {
18
- return {
19
- triggerCharacters: [' ', '$', '@', '.', '"', '/'],
20
-
21
- provideCompletionItems(model, position) {
22
- const lines = model.getLinesContent();
23
- const lineIndex = position.lineNumber - 1;
24
- const currentLine = lines[lineIndex] ?? '';
25
- const textBefore = currentLine.substring(0, position.column - 1);
26
- const plan = planCompletions(lines, lineIndex, textBefore);
27
- if (plan.kind === 'none') return { suggestions: [] };
28
-
29
- const symbols = scanDocument(lines);
30
- const word = model.getWordUntilPosition(position);
31
- const range = new monaco.Range(
32
- position.lineNumber,
33
- word.startColumn,
34
- position.lineNumber,
35
- word.endColumn,
36
- );
37
- const kinds = monaco.languages.CompletionItemKind;
38
- const asSnippet = monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet;
39
-
40
- const snippet = (entry: CompletionEntry): languages.CompletionItem => ({
41
- label: entry.label,
42
- kind: entry.insertText.includes('$') ? kinds.Snippet : kinds.Keyword,
43
- insertText: entry.insertText,
44
- insertTextRules: asSnippet,
45
- documentation: entry.documentation,
46
- range,
47
- });
48
- const symbolItem = (
49
- name: string,
50
- kind: languages.CompletionItemKind,
51
- detail: string,
52
- ): languages.CompletionItem => ({
53
- label: name,
54
- kind,
55
- insertText: name,
56
- detail,
57
- range,
58
- });
59
- const eventNames = () => {
60
- const inlineNames = new Set(symbols.events.filter(event => event.inline).map(event => event.name));
61
- return [...new Set(knownEventNames(symbols))].map((name) => symbolItem(name, kinds.Event, inlineNames.has(name) ? 'inline event' : 'event'));
62
- };
63
-
64
- switch (plan.kind) {
65
- case 'playFiles': {
66
- const pathRange = new monaco.Range(
67
- position.lineNumber,
68
- position.column - plan.replaceLength,
69
- position.lineNumber,
70
- position.column,
71
- );
72
- return {
73
- suggestions: (options.playFiles?.(model) ?? []).map((path) => ({
74
- label: path,
75
- kind: path.includes('*') ? kinds.Folder : kinds.File,
76
- insertText: path,
77
- range: pathRange,
78
- })),
79
- };
80
- }
81
- case 'contextVariables': {
82
- const variableRange = new monaco.Range(
83
- position.lineNumber,
84
- position.column - plan.replaceLength,
85
- position.lineNumber,
86
- word.endColumn,
87
- );
88
- return {
89
- suggestions: contextVariableItems.map((entry) => ({
90
- ...snippet(entry),
91
- range: variableRange,
92
- })),
93
- };
94
- }
95
- case 'policies':
96
- return {
97
- suggestions: symbols.policies.map((policy) =>
98
- symbolItem(policy.name, kinds.Reference, 'policy'),
99
- ),
100
- };
101
- case 'events':
102
- return { suggestions: eventNames() };
103
- case 'triggers':
104
- return {
105
- suggestions: [...new Set(knownTriggerNames(symbols))].map((name) =>
106
- symbolItem(name, kinds.Event, 'trigger'),
107
- ),
108
- };
109
- case 'commands':
110
- return {
111
- suggestions: symbols.commands.map((command) =>
112
- symbolItem(command.name, kinds.Method, 'command'),
113
- ),
114
- };
115
- case 'producesTargets':
116
- return { suggestions: [...producesItems.map(snippet), ...eventNames()] };
117
- case 'screens':
118
- return {
119
- suggestions: symbols.screens.map((screen) =>
120
- symbolItem(screen.name, kinds.Interface, 'screen'),
121
- ),
122
- };
123
- case 'queries':
124
- return {
125
- suggestions: symbols.queries.map((query) =>
126
- symbolItem(query.name, kinds.Function, `query => ${query.returnType}`),
127
- ),
128
- };
129
- case 'types':
130
- return {
131
- suggestions: [
132
- ...symbols.concepts.map((concept) =>
133
- symbolItem(
134
- concept.name,
135
- kinds.Class,
136
- `concept : ${concept.primitive}${concept.attributes.length ? ' ' + concept.attributes.join(' ') : ''}`,
137
- ),
138
- ),
139
- ...symbols.types.map((type) =>
140
- symbolItem(
141
- type.name,
142
- kinds.Struct,
143
- `type (${type.properties.length} properties)`,
144
- ),
145
- ),
146
- ...primitiveTypes.map((primitive) =>
147
- symbolItem(primitive, kinds.Struct, 'primitive'),
148
- ),
149
- ],
150
- };
151
- case 'entries':
152
- return { suggestions: plan.entries.map(snippet) };
153
- }
154
- },
155
- };
156
- }
@@ -1,43 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- // The PLAY codes the editor reports. Every one of them mirrors a condition the compiler checks and
5
- // carries the compiler's own code for it, so the same problem is called the same thing whether it was
6
- // found by the CLI or by a squiggle - see Documentation/screenplay/diagnostics.md for the catalogue.
7
- //
8
- // A code is only ever added here for a condition the compiler can also report. The editor makes a few
9
- // structural checks the compiler does not - the capture and projection validators are where they live -
10
- // and those stay codeless deliberately: minting a PLAY number for something no compiler run can emit
11
- // would make the catalogue describe two different tools.
12
- export const diagnosticCodes = {
13
- eventSourceIdInPayload: 'PLAY0469',
14
- explicitProducesTargetsRequired: 'PLAY0470',
15
- redundantEventId: 'PLAY0471',
16
- invalidEventId: 'PLAY0472',
17
- inlineEventCollision: 'PLAY0473',
18
- inlineEventOutsideCommand: 'PLAY0474',
19
- inlineEventGeneration: 'PLAY0475',
20
- reservedProductionMetadata: 'PLAY0476',
21
- invalidEventDocumentation: 'PLAY0477',
22
- tabIndentation: 'PLAY0006',
23
- unknownPrimitiveType: 'PLAY0008',
24
- unknownSliceType: 'PLAY0028',
25
- duplicateCommandIdentifier: 'PLAY0036',
26
- unknownContextPath: 'PLAY0153',
27
- unknownContextCausedByProperty: 'PLAY0154',
28
- unknownContextIdentityProperty: 'PLAY0155',
29
- unclosedCodeBlock: 'PLAY0164',
30
- unknownType: 'PLAY0165',
31
- unknownEvent: 'PLAY0166',
32
- unknownPolicy: 'PLAY0167',
33
- duplicateDeclaration: 'PLAY0168',
34
- unknownEventContextMember: 'PLAY0295',
35
- unknownEventContextPath: 'PLAY0296',
36
- eventContextPathBelowCollection: 'PLAY0297',
37
- missingEventContextPath: 'PLAY0298',
38
- unresolvedDynamicKeySource: 'PLAY0299',
39
- invalidFileImport: 'PLAY0454',
40
- omittedProductionDestination: 'PLAY0478',
41
- } as const;
42
-
43
- export type DiagnosticCode = (typeof diagnosticCodes)[keyof typeof diagnosticCodes];