@cratis/screenplay-language 4.51.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,135 +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
- // Generated from Cratis.Screenplay.Syntax.EventContextCatalog - do not edit by hand. The spec
5
- // Syntax/for_EventContextCatalog/when_holding_the_editor_catalog_to_it fails when this file drifts; rerun
6
- // it with SCREENPLAY_REGENERATE_EVENT_CONTEXT=1 to rewrite it.
7
-
8
- export type EventContextMemberKind = 'value' | 'composite' | 'collection' | 'function';
9
-
10
- export interface EventContextMember {
11
- readonly name: string;
12
- readonly type: string;
13
- readonly kind: EventContextMemberKind;
14
- readonly description: string;
15
- }
16
-
17
- export interface EventContextPath extends EventContextMember {
18
- readonly path: string;
19
- }
20
-
21
- export const eventContextRootType = 'EventContext';
22
-
23
- // The members of each type a path passes through, keyed by type name.
24
- export const eventContextTypes: Readonly<Record<string, readonly EventContextMember[]>> = {
25
- 'EventContext': [
26
- { name: 'eventType', type: 'EventType', kind: 'composite', description: 'The type of the event - its identifier, generation and whether it is a tombstone.' },
27
- { name: 'eventSourceType', type: 'EventSourceType', kind: 'value', description: 'The type of the event source the event was appended to.' },
28
- { name: 'eventSourceId', type: 'EventSourceId', kind: 'value', description: 'The identifier of the event source the event was appended to - the value $eventSourceId resolves.' },
29
- { name: 'eventStreamType', type: 'EventStreamType', kind: 'value', description: 'The type of the event stream the event belongs to.' },
30
- { name: 'eventStreamId', type: 'EventStreamId', kind: 'value', description: 'The identifier of the event stream the event belongs to.' },
31
- { name: 'sequenceNumber', type: 'EventSequenceNumber', kind: 'value', description: 'The position of the event in its event sequence.' },
32
- { name: 'occurred', type: 'DateTimeOffset', kind: 'value', description: 'When the event occurred - the time it was appended unless one was given.' },
33
- { name: 'eventStore', type: 'EventStoreName', kind: 'value', description: 'The name of the event store the event belongs to.' },
34
- { name: 'namespace', type: 'EventStoreNamespaceName', kind: 'value', description: 'The namespace within the event store the event belongs to.' },
35
- { name: 'correlationId', type: 'CorrelationId', kind: 'value', description: 'The correlation identifier the event was appended with.' },
36
- { name: 'causation', type: 'IEnumerable<Causation>', kind: 'collection', description: 'The chain of causes that led to the event - a collection, not addressable below.' },
37
- { name: 'causedBy', type: 'Identity', kind: 'composite', description: 'The identity that caused the event.' },
38
- { name: 'tags', type: 'IEnumerable<Tag>', kind: 'collection', description: 'The tags the event was appended with - a collection, not addressable below.' },
39
- { name: 'hash', type: 'EventHash', kind: 'value', description: 'The hash of the event content.' },
40
- { name: 'observationState', type: 'EventObservationState', kind: 'value', description: 'Whether the observer sees the event for the first time or again on replay - differs between live processing and replay.' },
41
- { name: 'subject', type: 'Subject', kind: 'value', description: 'The compliance subject the event is about - the event source identifier unless one was given.' },
42
- { name: 'subjectIsEventSourceId', type: 'bool', kind: 'value', description: 'Whether the subject is the event source identifier.' },
43
- ],
44
- 'EventType': [
45
- { name: 'id', type: 'EventTypeId', kind: 'value', description: 'The identifier of the event type.' },
46
- { name: 'generation', type: 'EventTypeGeneration', kind: 'value', description: 'The generation of the event type.' },
47
- { name: 'tombstone', type: 'bool', kind: 'value', description: 'Whether the event is a tombstone event.' },
48
- ],
49
- 'EventSourceType': [
50
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
51
- ],
52
- 'EventSourceId': [
53
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
54
- ],
55
- 'EventStreamType': [
56
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
57
- ],
58
- 'EventStreamId': [
59
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
60
- ],
61
- 'EventSequenceNumber': [
62
- { name: 'value', type: 'ulong', kind: 'value', description: 'The underlying ulong value.' },
63
- ],
64
- 'DateTimeOffset': [
65
- { name: 'Week', type: 'int', kind: 'function', description: 'The ISO 8601 week of the year the value falls in.' },
66
- ],
67
- 'EventStoreName': [
68
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
69
- ],
70
- 'EventStoreNamespaceName': [
71
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
72
- ],
73
- 'CorrelationId': [
74
- { name: 'value', type: 'Guid', kind: 'value', description: 'The underlying Guid value.' },
75
- ],
76
- 'Identity': [
77
- { name: 'subject', type: 'string', kind: 'value', description: 'The subject identifier of the identity.' },
78
- { name: 'name', type: 'string', kind: 'value', description: 'The display name of the identity.' },
79
- { name: 'userName', type: 'string', kind: 'value', description: 'The user name of the identity.' },
80
- { name: 'onBehalfOf', type: 'Identity', kind: 'composite', description: 'The identity this identity acted on behalf of, if any - an identity with the same members.' },
81
- ],
82
- 'EventHash': [
83
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
84
- ],
85
- 'Subject': [
86
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
87
- ],
88
- 'EventTypeId': [
89
- { name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
90
- ],
91
- 'EventTypeGeneration': [
92
- { name: 'value', type: 'uint', kind: 'value', description: 'The underlying uint value.' },
93
- ],
94
- };
95
-
96
- // Every path the catalog lists, depth first in declaration order.
97
- export const eventContextPaths: readonly EventContextPath[] = [
98
- { path: 'eventType', name: 'eventType', type: 'EventType', kind: 'composite', description: 'The type of the event - its identifier, generation and whether it is a tombstone.' },
99
- { path: 'eventType.id', name: 'id', type: 'EventTypeId', kind: 'value', description: 'The identifier of the event type.' },
100
- { path: 'eventType.id.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
101
- { path: 'eventType.generation', name: 'generation', type: 'EventTypeGeneration', kind: 'value', description: 'The generation of the event type.' },
102
- { path: 'eventType.generation.value', name: 'value', type: 'uint', kind: 'value', description: 'The underlying uint value.' },
103
- { path: 'eventType.tombstone', name: 'tombstone', type: 'bool', kind: 'value', description: 'Whether the event is a tombstone event.' },
104
- { path: 'eventSourceType', name: 'eventSourceType', type: 'EventSourceType', kind: 'value', description: 'The type of the event source the event was appended to.' },
105
- { path: 'eventSourceType.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
106
- { path: 'eventSourceId', name: 'eventSourceId', type: 'EventSourceId', kind: 'value', description: 'The identifier of the event source the event was appended to - the value $eventSourceId resolves.' },
107
- { path: 'eventSourceId.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
108
- { path: 'eventStreamType', name: 'eventStreamType', type: 'EventStreamType', kind: 'value', description: 'The type of the event stream the event belongs to.' },
109
- { path: 'eventStreamType.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
110
- { path: 'eventStreamId', name: 'eventStreamId', type: 'EventStreamId', kind: 'value', description: 'The identifier of the event stream the event belongs to.' },
111
- { path: 'eventStreamId.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
112
- { path: 'sequenceNumber', name: 'sequenceNumber', type: 'EventSequenceNumber', kind: 'value', description: 'The position of the event in its event sequence.' },
113
- { path: 'sequenceNumber.value', name: 'value', type: 'ulong', kind: 'value', description: 'The underlying ulong value.' },
114
- { path: 'occurred', name: 'occurred', type: 'DateTimeOffset', kind: 'value', description: 'When the event occurred - the time it was appended unless one was given.' },
115
- { path: 'occurred.Week', name: 'Week', type: 'int', kind: 'function', description: 'The ISO 8601 week of the year the value falls in.' },
116
- { path: 'eventStore', name: 'eventStore', type: 'EventStoreName', kind: 'value', description: 'The name of the event store the event belongs to.' },
117
- { path: 'eventStore.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
118
- { path: 'namespace', name: 'namespace', type: 'EventStoreNamespaceName', kind: 'value', description: 'The namespace within the event store the event belongs to.' },
119
- { path: 'namespace.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
120
- { path: 'correlationId', name: 'correlationId', type: 'CorrelationId', kind: 'value', description: 'The correlation identifier the event was appended with.' },
121
- { path: 'correlationId.value', name: 'value', type: 'Guid', kind: 'value', description: 'The underlying Guid value.' },
122
- { path: 'causation', name: 'causation', type: 'IEnumerable<Causation>', kind: 'collection', description: 'The chain of causes that led to the event - a collection, not addressable below.' },
123
- { path: 'causedBy', name: 'causedBy', type: 'Identity', kind: 'composite', description: 'The identity that caused the event.' },
124
- { path: 'causedBy.subject', name: 'subject', type: 'string', kind: 'value', description: 'The subject identifier of the identity.' },
125
- { path: 'causedBy.name', name: 'name', type: 'string', kind: 'value', description: 'The display name of the identity.' },
126
- { path: 'causedBy.userName', name: 'userName', type: 'string', kind: 'value', description: 'The user name of the identity.' },
127
- { path: 'causedBy.onBehalfOf', name: 'onBehalfOf', type: 'Identity', kind: 'composite', description: 'The identity this identity acted on behalf of, if any - an identity with the same members.' },
128
- { path: 'tags', name: 'tags', type: 'IEnumerable<Tag>', kind: 'collection', description: 'The tags the event was appended with - a collection, not addressable below.' },
129
- { path: 'hash', name: 'hash', type: 'EventHash', kind: 'value', description: 'The hash of the event content.' },
130
- { path: 'hash.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
131
- { path: 'observationState', name: 'observationState', type: 'EventObservationState', kind: 'value', description: 'Whether the observer sees the event for the first time or again on replay - differs between live processing and replay.' },
132
- { path: 'subject', name: 'subject', type: 'Subject', kind: 'value', description: 'The compliance subject the event is about - the event source identifier unless one was given.' },
133
- { path: 'subject.value', name: 'value', type: 'string', kind: 'value', description: 'The underlying string value.' },
134
- { path: 'subjectIsEventSourceId', name: 'subjectIsEventSourceId', type: 'bool', kind: 'value', description: 'Whether the subject is the event source identifier.' },
135
- ];
package/event-context.ts DELETED
@@ -1,119 +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
- // Reads the generated event-context catalog. Every editor surface that describes $eventContext - projection
5
- // completion and hover, and the host editor's context-variable docs and completions - goes through here, so
6
- // none of them carries a list of its own.
7
-
8
- import { eventContextPaths, eventContextRootType, eventContextTypes } from './event-context-catalog';
9
- import type { EventContextMember, EventContextPath } from './event-context-catalog';
10
-
11
- export { eventContextPaths };
12
- export type { EventContextMember, EventContextPath };
13
-
14
- /**
15
- * Whether a written path segment names a member. Mirrors EventContextMember.IsNamedBy in the compiler: a property
16
- * resolves camelCase or with only its first character uppercased; a function resolves by its exact name, with or
17
- * without parentheses.
18
- */
19
- export function namesEventContextMember(member: EventContextMember, segment: string): boolean {
20
- if (member.kind === 'function') {
21
- return segment === member.name || segment === `${member.name}()`;
22
- }
23
-
24
- const declared = member.name[0].toUpperCase() + member.name.slice(1);
25
- return segment === declared || (segment.length > 0 && segment[0].toUpperCase() + segment.slice(1) === declared);
26
- }
27
-
28
- /** The members of the event context itself - the first segment of every path. */
29
- export const eventContextMembers: readonly EventContextMember[] = eventContextTypes[eventContextRootType];
30
-
31
- /**
32
- * The members that may follow the given segments after `$eventContext.`, or undefined when the segments do not
33
- * resolve or stop at a collection or function, below which nothing is addressable.
34
- */
35
- export function eventContextMembersAfter(segments: readonly string[]): readonly EventContextMember[] | undefined {
36
- let members = eventContextMembers;
37
- for (const segment of segments) {
38
- const member = members.find((candidate) => namesEventContextMember(candidate, segment));
39
- if (!member || member.kind === 'collection' || member.kind === 'function') {
40
- return undefined;
41
- }
42
-
43
- members = eventContextTypes[member.type] ?? [];
44
- }
45
-
46
- return members;
47
- }
48
-
49
- /** The member the given segments name, or undefined when they do not resolve. */
50
- export function eventContextMemberAt(segments: readonly string[]): EventContextMember | undefined {
51
- if (segments.length === 0) {
52
- return undefined;
53
- }
54
-
55
- const members = eventContextMembersAfter(segments.slice(0, -1));
56
- return members?.find((member) => namesEventContextMember(member, segments[segments.length - 1]));
57
- }
58
-
59
- /** The outcome of resolving a path against the catalog. Mirrors EventContextPathStatus in the compiler. */
60
- export type EventContextPathStatus = 'known' | 'missing' | 'unknownMember' | 'unknownSubPath' | 'belowCollection';
61
-
62
- /** A path resolved against the catalog. Mirrors EventContextPathResolution in the compiler. */
63
- export interface EventContextPathResolution {
64
- readonly status: EventContextPathStatus;
65
- readonly member?: EventContextMember;
66
- readonly segment?: string;
67
- readonly expected: readonly EventContextMember[];
68
- }
69
-
70
- /**
71
- * Resolves a path, as written after `$eventContext.`, the way EventContextCatalog.Resolve in the compiler does, so the
72
- * editor reports what the compiler reports.
73
- */
74
- export function resolveEventContextPath(path: string): EventContextPathResolution {
75
- let current: EventContextMember | undefined;
76
- let expected = eventContextMembers;
77
- for (const segment of path.split('.')) {
78
- if (segment.length === 0) {
79
- return { status: 'missing', member: current, expected };
80
- }
81
-
82
- if (current?.kind === 'collection') {
83
- return { status: 'belowCollection', member: current, segment, expected: [] };
84
- }
85
-
86
- const next = expected.find((member) => namesEventContextMember(member, segment));
87
- if (!next) {
88
- return { status: current ? 'unknownSubPath' : 'unknownMember', member: current, segment, expected };
89
- }
90
-
91
- current = next;
92
- expected = next.kind === 'function' ? [] : eventContextTypes[next.type] ?? [];
93
- }
94
-
95
- return { status: 'known', member: current, expected: [] };
96
- }
97
-
98
- /** Markdown describing $eventContext and its members, for hovers. */
99
- export function describeEventContext(): string {
100
- return [
101
- '**$eventContext**',
102
- '',
103
- 'Metadata about the event being projected. Paths are checked against the event-context catalog; `causation` and `tags` are collections and cannot be addressed below.',
104
- '',
105
- '**Members:**',
106
- ...eventContextMembers.map((member) => `- \`${member.name}\` (${member.type}) - ${member.description}`),
107
- ].join('\n');
108
- }
109
-
110
- /** Markdown describing one member of the event context, for hovers. */
111
- export function describeEventContextMember(path: string, member: EventContextMember): string {
112
- const below = member.kind === 'collection' || member.kind === 'function' ? [] : eventContextTypes[member.type] ?? [];
113
- const lines = [`**$eventContext.${path}**: \`${member.type}\``, '', member.description];
114
- if (below.length > 0) {
115
- lines.push('', `**Members:** ${below.map((child) => `\`${child.name}\``).join(', ')}`);
116
- }
117
-
118
- return lines.join('\n');
119
- }
package/file-imports.ts DELETED
@@ -1,70 +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 { fenceMap, indentOf } from './document-context';
5
-
6
- // An `import "<path or glob>"` of other .play files, with the pattern exactly as written and the span it
7
- // occupies between the quotes. Columns are one-based like every other position this package reports.
8
- export interface FileImport {
9
- pattern: string;
10
- line: number;
11
- startColumn: number;
12
- endColumn: number;
13
- }
14
-
15
- // The compiler's own shape for a file import (FileImportParser): a quoted operand without quotes or escapes.
16
- const fileImportPattern = /^import(\s+)"([^"\\]+)"\s*(?:\/\/.*)?$/;
17
- const quotedImportPattern = /^import\s+"/;
18
-
19
- // Whether a line imports files rather than a qualified name - its operand is quoted.
20
- export function isFileImportLine(line: string): boolean {
21
- return quotedImportPattern.test(line.trim());
22
- }
23
-
24
- // The file import on a single line, or undefined when the line is not a well-formed one.
25
- export function fileImportOn(line: string, lineIndex: number): FileImport | undefined {
26
- const indent = indentOf(line);
27
- const match = line.slice(indent).match(fileImportPattern);
28
- if (!match) return undefined;
29
- const startColumn = indent + 'import'.length + match[1].length + 2;
30
- return { pattern: match[2], line: lineIndex, startColumn, endColumn: startColumn + match[2].length };
31
- }
32
-
33
- // Every well-formed file import in a document, in document order, skipping code fences.
34
- export function fileImports(lines: string[]): FileImport[] {
35
- const fences = fenceMap(lines);
36
- const found: FileImport[] = [];
37
- for (let index = 0; index < lines.length; index++) {
38
- if (fences[index]) continue;
39
- const fileImport = fileImportOn(lines[index], index);
40
- if (fileImport) found.push(fileImport);
41
- }
42
- return found;
43
- }
44
-
45
- const folderOf = (path: string): string[] => path.split('/').slice(0, -1);
46
-
47
- function relativeTo(from: readonly string[], path: string): string {
48
- const segments = path.split('/');
49
- let common = 0;
50
- while (common < from.length && common < segments.length - 1 && from[common] === segments[common]) common++;
51
- return [...from.slice(common).map(() => '..'), ...segments.slice(common)].join('/');
52
- }
53
-
54
- // What an import written in a document can name: every other .play file, relative to the document's folder;
55
- // a glob for the files directly in each folder holding one; and a glob for everything beneath each folder on
56
- // the way to them. Paths are portable ('/' separated) and relative to one root, the way the compiler resolves them.
57
- export function importablePaths(documentPath: string, files: readonly string[]): string[] {
58
- const from = folderOf(documentPath);
59
- const paths = new Set<string>();
60
- for (const file of files.filter((candidate) => candidate !== documentPath && candidate.toLowerCase().endsWith('.play'))) {
61
- const relative = relativeTo(from, file);
62
- const folders = folderOf(relative);
63
- paths.add(relative);
64
- paths.add([...folders, '*.play'].join('/'));
65
- for (let depth = 0; depth <= folders.length; depth++) {
66
- paths.add([...folders.slice(0, depth), '**', '*.play'].join('/'));
67
- }
68
- }
69
- return [...paths].sort();
70
- }
@@ -1,87 +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 { fenceMap, firstWord, indentOf } from './document-context';
5
-
6
- // The keyword the directive opens with — the single word the language points at a file with.
7
- export const fileReferenceKeyword = 'file';
8
-
9
- // A `file <path>` directive, with the path exactly as written and the span it occupies on its line.
10
- // The span is measured against the raw line, and its columns are one-based like every other position
11
- // this package reports, so an editor places a range on it the same way it does a validation issue.
12
- export interface FileReference {
13
- path: string;
14
- line: number;
15
- startColumn: number;
16
- endColumn: number;
17
- }
18
-
19
- // `file String` is a property named `file`; `file Invoices/Register.cs` is the directive. The two are
20
- // told apart by shape, the way the compiler tells them apart: a type reference is a bare identifier,
21
- // so anything carrying a separator or an extension is a path and nothing else. The property wins the
22
- // tie, because a document that used the name before the directive existed keeps meaning what it meant.
23
- const typeReferencePattern = /^[A-Za-z_]\w*(?:\[\])?\??$/;
24
-
25
- // A path naming a place on one machine rather than a place in the repository. The compiler warns about
26
- // these; nothing here rejects one, so a resolver can still probe it and come up empty on other machines.
27
- const absolutePathPattern = /^(?:[/\\]|[A-Za-z]:[/\\]|~[/\\])/;
28
-
29
- export function isAbsoluteFileReferencePath(path: string): boolean {
30
- return absolutePathPattern.test(path);
31
- }
32
-
33
- // Drops a trailing `//` comment without cutting into a string or a template, mirroring how the
34
- // compiler strips one before it reads the line.
35
- function withoutComment(text: string): string {
36
- let inString = false;
37
- let inTemplate = false;
38
-
39
- for (let index = 0; index < text.length; index++) {
40
- const current = text[index];
41
- if (current === '\\' && inString && index + 1 < text.length) {
42
- index++;
43
- } else if (current === '"' && !inTemplate) {
44
- inString = !inString;
45
- } else if (current === '`' && !inString) {
46
- inTemplate = !inTemplate;
47
- } else if (!inString && !inTemplate && current === '/' && text[index + 1] === '/') {
48
- return text.slice(0, index);
49
- }
50
- }
51
-
52
- return text;
53
- }
54
-
55
- // The `file` directive on a single line, or undefined when the line is not one. Callers that scan a
56
- // whole document go through fileReferences instead, so code fences are accounted for.
57
- export function fileReferenceOn(line: string, lineIndex: number): FileReference | undefined {
58
- const indent = indentOf(line);
59
- const content = withoutComment(line.slice(indent)).trimEnd();
60
- if (firstWord(content) !== fileReferenceKeyword) return undefined;
61
-
62
- const afterKeyword = content.slice(fileReferenceKeyword.length);
63
- const path = afterKeyword.trim();
64
-
65
- // A bare `file` leaves the word available as a name to whatever the enclosing block reads a bare
66
- // word as, and a bare identifier after it is a property type rather than a path.
67
- if (path.length === 0 || typeReferencePattern.test(path)) return undefined;
68
-
69
- const separatorLength = afterKeyword.length - afterKeyword.trimStart().length;
70
- const startColumn = indent + fileReferenceKeyword.length + separatorLength + 1;
71
- return { path, line: lineIndex, startColumn, endColumn: startColumn + path.length };
72
- }
73
-
74
- // Every `file` directive in a document, in document order. Lines inside a code fence are skipped, so
75
- // a `file` line in an inline C# or TypeScript block is never mistaken for one of ours.
76
- export function fileReferences(lines: string[]): FileReference[] {
77
- const fences = fenceMap(lines);
78
- const references: FileReference[] = [];
79
-
80
- for (let index = 0; index < lines.length; index++) {
81
- if (fences[index]) continue;
82
- const reference = fileReferenceOn(lines[index], index);
83
- if (reference) references.push(reference);
84
- }
85
-
86
- return references;
87
- }
@@ -1,32 +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 { describe, expect, it } from 'vitest';
5
- import { enclosingChain, fenceMap, nearestEnclosingLine, withoutComment } from '../document-context';
6
-
7
- // The same cases are asserted against C# SourceLineSplitter in when_stripping_comments.cs.
8
- const cases = [
9
- ['value = path // comment', 'value = path'],
10
- ['value = "https://example" // comment', 'value = "https://example"'],
11
- [String.raw`value = "escaped \" // retained" // comment`, String.raw`value = "escaped \" // retained"`],
12
- [String.raw`value = "ending \\" // comment`, String.raw`value = "ending \\"`],
13
- ['value = `https://example` // comment', 'value = `https://example`'],
14
- ['value = `a " // retained` // comment', 'value = `a " // retained`'],
15
- ['value = "a ` // retained" // comment', 'value = "a ` // retained"'],
16
- ['value = "unclosed // retained', 'value = "unclosed // retained'],
17
- ['value = `unclosed // retained', 'value = `unclosed // retained'],
18
- ['value = path # not a comment', 'value = path # not a comment'],
19
- ["value = 'single // comment", "value = 'single"],
20
- ];
21
-
22
- describe('when stripping structural comments', () => {
23
- it.each(cases)('should match SourceLineSplitter for %s', (line, expected) => {
24
- withoutComment(line).trimEnd().should.equal(expected);
25
- });
26
-
27
- it('should skip comment-only lines when finding an enclosing block', () => {
28
- const lines = ['command Register // explanation', ' // comment', ' produces Registered'];
29
- enclosingChain(lines, fenceMap(lines), 2, 4).should.deep.equal(['command']);
30
- expect(nearestEnclosingLine(lines, fenceMap(lines), 2, 4)).toBe('command Register');
31
- });
32
- });
@@ -1,15 +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 { describe, expect, it } from 'vitest';
5
- import vectors from '../event-context-resolution-vectors.json';
6
- import { resolveEventContextPath } from '../event-context';
7
-
8
- describe('when resolving paths generated from the C# event-context catalog', () => {
9
- it('agrees with C# on every known, missing and invalid path', () => {
10
- expect(vectors.length).toBeGreaterThan(50);
11
- for (const vector of vectors) {
12
- expect(resolveEventContextPath(vector.path).status, vector.path).toBe(vector.status);
13
- }
14
- });
15
- });
@@ -1,57 +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 { describe, it } from 'vitest';
5
- import type { editor, languages, Position } from 'monaco-editor';
6
- import { createCompletionProvider } from '../completions';
7
- import type { Monaco } from '../language';
8
- import { createTokensProvider } from '../tokens';
9
- import { hoverContent } from '../hover-content';
10
- import { scanDocument } from '../symbols';
11
-
12
- const lines = [
13
- 'event Registered generation 1',
14
- ' old String',
15
- 'event Registered generation 2',
16
- ' generation String',
17
- ' current String',
18
- ' note = $eventContext.eventType.generation',
19
- ];
20
-
21
- describe('when editing event generations', () => {
22
- it('should recognize the marker only on a complete event header', () => {
23
- const rules = createTokensProvider([]).tokenizer.root;
24
- const headerRule = rules.find((rule) => Array.isArray(rule) && rule[0] instanceof RegExp && rule[0].source.includes('(generation)')) as [RegExp, string[]];
25
- headerRule.should.not.be.undefined;
26
- const header = lines[2].match(headerRule[0]);
27
- header?.[6].should.equal('generation');
28
- headerRule[1][5].should.equal('keyword');
29
- lines.slice(3).every((line) => !headerRule[0].test(line)).should.be.true;
30
- });
31
-
32
- it('should keep generation as a property name', () => {
33
- scanDocument(lines).events[1].properties.map((property) => property.name).should.include('generation');
34
- });
35
-
36
- it('should offer one completion per event name', () => {
37
- const source = [...lines.slice(0, 5), 'command Send', ' produces '];
38
- const model = {
39
- getLinesContent: () => source,
40
- getWordUntilPosition: () => ({ startColumn: 12, endColumn: 12 }),
41
- } as unknown as editor.ITextModel;
42
- const monaco = {
43
- Range: class { constructor(..._args: number[]) {} },
44
- languages: { CompletionItemKind: { Event: 1 }, CompletionItemInsertTextRule: { InsertAsSnippet: 4 } },
45
- } as unknown as Monaco;
46
- const provider = createCompletionProvider(monaco);
47
- const result = provider.provideCompletionItems!(model, { lineNumber: 7, column: 12 } as Position, {} as languages.CompletionContext, {} as never) as languages.CompletionList;
48
- result.suggestions.filter((item) => item.label === 'Registered').length.should.equal(1);
49
- });
50
-
51
- it('should hover over the generation declaration itself', () => {
52
- const hover = hoverContent(lines, 2, 'Registered', 7, 17);
53
- hover?.should.include('event Registered generation 2');
54
- hover?.should.include('current String');
55
- hover?.should.not.include('old String');
56
- });
57
- });
@@ -1,38 +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 { describe, beforeEach, it } from 'vitest';
5
- import { FileImport, fileImportOn, fileImports, isFileImportLine } from '../file-imports';
6
-
7
- describe('when finding file imports', () => {
8
- let found: FileImport[];
9
-
10
- beforeEach(() => {
11
- found = fileImports([
12
- 'import Customers.CustomerRegistered',
13
- 'import "**/*.play"',
14
- 'module Ordering',
15
- ' import "Orders/*.play" // the orders',
16
- ' screen Overview',
17
- ' ```typescript',
18
- 'import "not/a/play/import"',
19
- ' ```',
20
- ]);
21
- });
22
-
23
- it('should find the quoted imports outside code fences', () => {
24
- found.map((each) => each.pattern).should.deep.equal(['**/*.play', 'Orders/*.play']);
25
- });
26
-
27
- it('should locate the pattern between the quotes', () => {
28
- found[1].should.deep.equal({ pattern: 'Orders/*.play', line: 3, startColumn: 13, endColumn: 26 });
29
- });
30
-
31
- it('should not read a malformed import as one', () => {
32
- (fileImportOn('import "a\\b.play"', 0) === undefined).should.be.true;
33
- });
34
-
35
- it('should tell a file import from a qualified one by its quote', () => {
36
- [isFileImportLine(' import "x'), isFileImportLine('import X.Y')].should.deep.equal([true, false]);
37
- });
38
- });
@@ -1,26 +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 { describe, it } from 'vitest';
5
- import { isAbsoluteFileReferencePath } from '../../file-references';
6
-
7
- // A reference is relative to the repository root, so it means the same thing on every machine. An
8
- // absolute one names a place on one machine and is wrong without looking anything up.
9
- describe('when recognizing an absolute path', () => {
10
- it('should recognize a posix path', () => {
11
- isAbsoluteFileReferencePath('/Users/someone/Invoices/Register.cs').should.be.true;
12
- });
13
-
14
- it('should recognize a windows path', () => {
15
- isAbsoluteFileReferencePath('C:/repos/Invoices/Register.cs').should.be.true;
16
- isAbsoluteFileReferencePath('C:\\repos\\Invoices\\Register.cs').should.be.true;
17
- });
18
-
19
- it('should recognize a home-relative path', () => {
20
- isAbsoluteFileReferencePath('~/repos/Invoices/Register.cs').should.be.true;
21
- });
22
-
23
- it('should not recognize a repository-relative path', () => {
24
- isAbsoluteFileReferencePath('Invoices/Register.cs').should.be.false;
25
- });
26
- });
@@ -1,26 +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 { describe, beforeEach, it } from 'vitest';
5
- import { FileReference, fileReferences } from '../../file-references';
6
-
7
- // An inline C# block may well contain the word `file` at the start of a line — it is a C# modifier —
8
- // and none of it is Screenplay.
9
- describe('when scanning a document with a file line inside a code fence', () => {
10
- let result: FileReference[];
11
-
12
- beforeEach(() => {
13
- result = fileReferences([
14
- 'handler',
15
- ' ```csharp',
16
- ' file static class Helpers/NotAPath.cs',
17
- ' ```',
18
- ' file Handlers/Real.cs',
19
- ]);
20
- });
21
-
22
- it('should find only the reference outside the fence', () => {
23
- result.should.have.lengthOf(1);
24
- result[0].path.should.equal('Handlers/Real.cs');
25
- });
26
- });
@@ -1,19 +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 { describe, beforeEach, it } from 'vitest';
5
- import { FileReference, fileReferences } from '../../file-references';
6
-
7
- // A bare `file` carries no path, so it leaves the word available as a name to whatever the enclosing
8
- // block reads a bare word as.
9
- describe('when scanning a document with a bare file keyword', () => {
10
- let result: FileReference[];
11
-
12
- beforeEach(() => {
13
- result = fileReferences(['reaction', ' file', ' file ', 'filename Something.cs']);
14
- });
15
-
16
- it('should find no reference', () => {
17
- result.should.be.empty;
18
- });
19
- });