@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,193 +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 { languages } from 'monaco-editor';
5
-
6
- export const languageId = 'pdl';
7
-
8
- // Keywords for the Projection Declaration Language
9
- const KEYWORDS = [
10
- 'projection',
11
- 'sequence',
12
- 'all',
13
- 'every',
14
- 'on',
15
- 'from',
16
- 'key',
17
- 'parent',
18
- 'join',
19
- 'automap',
20
- 'no',
21
- 'children',
22
- 'nested',
23
- 'identified',
24
- 'by',
25
- 'add',
26
- 'subtract',
27
- 'remove',
28
- 'via',
29
- 'with',
30
- 'default',
31
- 'increment',
32
- 'decrement',
33
- 'count',
34
- 'set',
35
- 'unset',
36
- 'clear',
37
- 'events',
38
- 'id',
39
- 'exclude',
40
- 'variant',
41
- 'enters',
42
- ] as const;
43
-
44
- // Built-in expressions and functions
45
- const BUILTINS = [
46
- '$eventSourceId',
47
- '$causedBy',
48
- '$eventContext',
49
- ] as const;
50
-
51
- // Operators
52
- const OPERATORS = ['=', '+=', '-=', '=>', '.'];
53
-
54
- export const configuration: languages.LanguageConfiguration = {
55
- comments: {
56
- lineComment: '#',
57
- },
58
- brackets: [
59
- ['{', '}'],
60
- ['[', ']'],
61
- ['(', ')'],
62
- ],
63
- autoClosingPairs: [
64
- { open: '{', close: '}' },
65
- { open: '[', close: ']' },
66
- { open: '(', close: ')' },
67
- { open: '"', close: '"' },
68
- { open: "'", close: "'" },
69
- { open: '`', close: '`' },
70
- ],
71
- surroundingPairs: [
72
- { open: '{', close: '}' },
73
- { open: '[', close: ']' },
74
- { open: '(', close: ')' },
75
- { open: '"', close: '"' },
76
- { open: "'", close: "'" },
77
- { open: '`', close: '`' },
78
- ],
79
- indentationRules: {
80
- increaseIndentPattern: /^.*(:|\bon\b|\ball\b|\bevery\b|\bchildren\b|\bnested\b|\bparent\b|\bvariant\b)\s*$/,
81
- decreaseIndentPattern: /^.*\}.*$/,
82
- },
83
- folding: {
84
- offSide: true,
85
- markers: {
86
- start: /^\s*(projection|all|every|on|children|nested|parent|variant)/,
87
- end: /^\s*$/,
88
- },
89
- },
90
- wordPattern: /@?[a-zA-Z_$][\w$-]*/,
91
- };
92
-
93
- export const monarchLanguage: languages.IMonarchLanguage = {
94
- defaultToken: '',
95
- tokenPostfix: '.pdl',
96
-
97
- keywords: KEYWORDS,
98
- builtins: BUILTINS,
99
- operators: OPERATORS,
100
-
101
- // Symbols
102
- symbols: /[=><!~?:&|+\-*/^%]+/,
103
- escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
104
-
105
- tokenizer: {
106
- root: [
107
- // Whitespace
108
- { include: '@whitespace' },
109
-
110
- // Template strings with ${...} interpolation
111
- [/`/, { token: 'string.template', next: '@templateString' }],
112
-
113
- // Escaped identifiers (@ prefix allows using keywords as identifiers)
114
- [/@[a-zA-Z_$][\w$]*/, 'identifier.escape'],
115
-
116
- // Check for uppercase keywords (error case - keywords must be lowercase)
117
- [
118
- /[A-Z][a-zA-Z_$][\w$]*/,
119
- {
120
- cases: {
121
- '@keywords': 'invalid',
122
- '@default': 'identifier',
123
- },
124
- },
125
- ],
126
-
127
- // Identifiers and keywords (lowercase only for keywords)
128
- [
129
- /[a-z_$][\w$]*/,
130
- {
131
- cases: {
132
- '@keywords': 'keyword',
133
- '@builtins': 'variable.predefined',
134
- '@default': 'identifier',
135
- },
136
- },
137
- ],
138
-
139
- // Delimiters and operators
140
- [/[{}()[\]]/, '@brackets'],
141
- [/=>/, 'operator.arrow'],
142
- [
143
- /@symbols/,
144
- {
145
- cases: {
146
- '@operators': 'operator',
147
- '@default': '',
148
- },
149
- },
150
- ],
151
-
152
- // Numbers
153
- [/\d*\.\d+([eE][-+]?\d+)?/, 'number.float'],
154
- [/0[xX][0-9a-fA-F]+/, 'number.hex'],
155
- [/\d+/, 'number'],
156
-
157
- // Delimiter: after number because of .\d floats
158
- [/[;,.]/, 'delimiter'],
159
-
160
- // Strings
161
- [/"([^"\\]|\\.)*$/, 'string.invalid'],
162
- [/"/, { token: 'string.quote', next: '@string' }],
163
- ],
164
-
165
- whitespace: [
166
- [/[ \t\r\n]+/, ''],
167
- [/#.*$/, 'comment'],
168
- ],
169
-
170
- // Template string state
171
- templateString: [
172
- [/\$\{/, { token: 'delimiter.bracket', next: '@templateExpression' }],
173
- [/[^\\`$]+/, 'string.template'],
174
- [/@escapes/, 'string.template.escape'],
175
- [/\\./, 'string.template.escape.invalid'],
176
- [/`/, { token: 'string.template', next: '@pop' }],
177
- ],
178
-
179
- // Template expression inside ${}
180
- templateExpression: [
181
- [/\}/, { token: 'delimiter.bracket', next: '@pop' }],
182
- { include: '@root' },
183
- ],
184
-
185
- // Regular string state
186
- string: [
187
- [/[^\\"]+/, 'string'],
188
- [/@escapes/, 'string.escape'],
189
- [/\\./, 'string.escape.invalid'],
190
- [/"/, { token: 'string.quote', next: '@pop' }],
191
- ],
192
- },
193
- };
package/symbols.ts DELETED
@@ -1,374 +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
- import { eventAnalysisSource } from './event-analysis-source';
6
- import { clauseKeywords } from './language';
7
- import { ProductionSymbol } from './ProductionSymbol';
8
-
9
- export interface PropertySymbol {
10
- name: string;
11
- type: string;
12
- isIdentifier: boolean;
13
- line: number;
14
- }
15
-
16
- export interface ConceptSymbol {
17
- name: string;
18
- primitive: string;
19
- attributes: string[];
20
- attributeReasons: Record<string, string>;
21
- enumValues: string[];
22
- line: number;
23
- }
24
-
25
- export interface TypeSymbol {
26
- name: string;
27
- properties: PropertySymbol[];
28
- line: number;
29
- }
30
-
31
- export interface PolicySymbol {
32
- name: string;
33
- requires: string[];
34
- line: number;
35
- }
36
-
37
- export interface EventSymbol {
38
- name: string;
39
- generation?: number;
40
- inline?: boolean;
41
- properties: PropertySymbol[];
42
- line: number;
43
- }
44
-
45
- export interface CommandSymbol extends NamedSymbol {
46
- properties: PropertySymbol[];
47
- reads?: ReadSymbol[];
48
- produces?: ProductionSymbol[];
49
- productionHeaders?: number[];
50
- }
51
-
52
- export interface ReadSymbol {
53
- view: string;
54
- alias?: string;
55
- by?: string;
56
- line: number;
57
- }
58
-
59
- export interface NamedSymbol {
60
- name: string;
61
- line: number;
62
- }
63
-
64
- export interface QuerySymbol extends NamedSymbol {
65
- returnType: string;
66
- parameters: PropertySymbol[];
67
- }
68
-
69
- export interface ImportSymbol {
70
- qualifiedName: string;
71
- shortName: string;
72
- line: number;
73
- }
74
-
75
- export interface DocumentSymbols {
76
- imports: ImportSymbol[];
77
- concepts: ConceptSymbol[];
78
- types: TypeSymbol[];
79
- policies: PolicySymbol[];
80
- events: EventSymbol[];
81
- commands: CommandSymbol[];
82
- queries: QuerySymbol[];
83
- screens: NamedSymbol[];
84
- triggers: NamedSymbol[];
85
- }
86
-
87
- const conceptPattern = /^concept\s+(\w+)\s*:\s*(\w+)((?:\s+@\w+)*)\s*$/;
88
- const propertyPattern = /^\s*(@?[a-z_]\w*)\s+([\w.]+(?:\[\])?\??)(\s+identifier)?\s*$/;
89
- const attributeReasonPattern = /^([a-z_]\w*)\s+reason\s+"((?:[^"\\]|\\.)*)"\s*$/;
90
- const readPattern = /^\s*reads\s+([A-Z]\w*)(?:\s+as\s+([a-z_]\w*))?(?:\s+by\s+([a-z_]\w*))?\s*$/;
91
- const commandReserved = ['authorize', 'produces', 'reads'];
92
- // AuthorizeParser's continuation pattern, including the compiler's Unicode word characters.
93
- const authorizationContinuation = /^(?:(?:or|and)\s+)?[A-Za-z_(][\p{L}\p{Mn}\p{Nd}\p{Pc}\s()]*$/u;
94
- const eventReserved = clauseKeywords.filter(keyword => !['id', 'description', 'documentation'].includes(keyword));
95
- const queryParameterPattern =
96
- /^\s*(?:by|filter)\s+([a-z_]\w*)\s+([\w.]+(?:\[\])?\??)(?:\s+from\s+.+)?\s*$/;
97
-
98
- // Property-shaped clauses depend on their owner. Commands reserve only authorize,
99
- // produces and reads; bare directives such as description and handler can be properties.
100
- // The @ escape always denotes a property, and 'as' keeps its established property meaning.
101
- function propertiesIn(lines: string[], body: number[], reserved: readonly string[]): PropertySymbol[] {
102
- return body
103
- .map((index) => ({ index, match: lines[index].match(propertyPattern) }))
104
- .filter((entry): entry is { index: number; match: RegExpMatchArray } => entry.match !== null)
105
- .filter(({ match }) => match[1].startsWith('@') || match[1] === 'as' || !reserved.includes(match[1]))
106
- .map(({ index, match }) => ({
107
- name: match[1].replace(/^@/, ''),
108
- type: match[2],
109
- isIdentifier: match[3] !== undefined,
110
- line: index,
111
- }));
112
- }
113
-
114
- function collectBody(lines: string[], fences: boolean[], start: number, indent: number): number[] {
115
- const body: number[] = [];
116
- for (let index = start + 1; index < lines.length; index++) {
117
- if (fences[index]) {
118
- continue;
119
- }
120
- const line = lines[index];
121
- if (line.trim().length === 0) continue;
122
- if (indentOf(line) <= indent) break;
123
- body.push(index);
124
- }
125
- return body;
126
- }
127
-
128
- // Event/production parsers accept every greater indent, not just the smallest child indent.
129
- // Command block directives own their nested lines; properties do not. Fenced prose is never syntax.
130
- export function directBody(lines: string[], fences: boolean[], start: number, indent: number): number[] {
131
- const body = collectBody(lines, fences, start, indent).filter(index => !fences[index] && !/^\s*(?:\/\/|#)/.test(lines[index]));
132
- if (!/^\s*command\b/.test(lines[start])) return body;
133
- let blockIndent: number | undefined;
134
- let authorization = false;
135
- return body.filter(index => {
136
- const childIndent = indentOf(lines[index]);
137
- const text = lines[index].trim();
138
- // AuthorizeParser owns only consecutive deeper lines with requirement shape.
139
- // Unlike opaque blocks, a nonmatching line returns control to CommandParser.
140
- if (blockIndent !== undefined && childIndent > blockIndent &&
141
- (!authorization || authorizationContinuation.test(text))) return false;
142
- const property = text !== 'validate csharp' && propertiesIn(lines, [index], commandReserved).length > 0;
143
- // Description consumes only a quoted value or a fence (already excluded above).
144
- const leaf = property || /^description(?:\s|$)/.test(text);
145
- blockIndent = leaf ? undefined : childIndent;
146
- authorization = /^authorize(?:\s|$)/.test(text);
147
- return true;
148
- });
149
- }
150
-
151
- export function scanDocument(lines: string[]): DocumentSymbols {
152
- const symbols: DocumentSymbols = {
153
- imports: [],
154
- concepts: [],
155
- types: [],
156
- policies: [],
157
- events: [],
158
- commands: [],
159
- queries: [],
160
- screens: [],
161
- triggers: [],
162
- };
163
- // One normalization pass for every declaration, including comments on fence openers.
164
- lines = eventAnalysisSource(lines);
165
- const fences = fenceMap(lines);
166
- const eventLines = lines;
167
- const eventFences = fences;
168
- // Typed inline mappings share property syntax once their source expression is removed.
169
- // Do this once, never once per inline event.
170
- const eventPropertyLines = lines.map(line => line.replace(/\s*=(?!=|>).*/, ''));
171
-
172
- for (let index = 0; index < lines.length; index++) {
173
- if (fences[index]) continue;
174
- const line = lines[index];
175
- const trimmed = line.trim();
176
- const indent = indentOf(line);
177
-
178
- const importMatch = eventLines[index].trim().match(/^import\s+([\w.]+)\s*$/);
179
- if (importMatch && indent === 0) {
180
- const qualifiedName = importMatch[1];
181
- const shortName = qualifiedName.split('.').pop() ?? qualifiedName;
182
- symbols.imports.push({ qualifiedName, shortName, line: index });
183
- continue;
184
- }
185
-
186
- const conceptMatch = trimmed.match(conceptPattern);
187
- if (conceptMatch) {
188
- const body = collectBody(lines, fences, index, indent).map((i) => lines[i].trim());
189
- const attributeReasons: Record<string, string> = {};
190
- for (const line of body) {
191
- const reason = line.match(attributeReasonPattern);
192
- if (reason && attributeReasons[reason[1]] === undefined) {
193
- attributeReasons[reason[1]] = reason[2];
194
- }
195
- }
196
- const enumValues =
197
- conceptMatch[2] === 'Enum'
198
- ? body.filter((line) => !attributeReasonPattern.test(line))
199
- : [];
200
- symbols.concepts.push({
201
- name: conceptMatch[1],
202
- primitive: conceptMatch[2],
203
- attributes: conceptMatch[3].trim().split(/\s+/).filter(Boolean),
204
- attributeReasons,
205
- enumValues,
206
- line: index,
207
- });
208
- continue;
209
- }
210
-
211
- const typeMatch = trimmed.match(/^type\s+(\w+)\s*$/);
212
- if (typeMatch) {
213
- symbols.types.push({
214
- name: typeMatch[1],
215
- properties: propertiesIn(lines, collectBody(lines, fences, index, indent), clauseKeywords),
216
- line: index,
217
- });
218
- continue;
219
- }
220
-
221
- const policyMatch = trimmed.match(/^policy\s+(\w+)\s*$/);
222
- if (policyMatch) {
223
- const requires = collectBody(lines, fences, index, indent)
224
- .filter((i) => !fences[i])
225
- .map((i) => lines[i].trim());
226
- symbols.policies.push({ name: policyMatch[1], requires, line: index });
227
- continue;
228
- }
229
-
230
- const eventMatch = eventLines[index].trim().match(/^(?:produces\s+)?event\s+(\w+)(?:\s+generation\s+(\d+))?\s*$/);
231
- if (eventMatch) {
232
- symbols.events.push({
233
- name: eventMatch[1],
234
- ...(eventMatch[2] ? { generation: Number(eventMatch[2]) } : {}),
235
- inline: trimmed.startsWith('produces '),
236
- properties: propertiesIn(trimmed.startsWith('produces ') ? eventPropertyLines : eventLines,
237
- directBody(eventLines, eventFences, index, indent), eventReserved),
238
- line: index,
239
- });
240
- continue;
241
- }
242
-
243
- const commandMatch = eventLines[index].trim().match(/^command\s+(\w+)\s*$/);
244
- if (commandMatch) {
245
- // A command property is a leaf, not an indentation owner. Share the parser-shaped
246
- // body with properties, productions, advice and destination hints.
247
- const body = directBody(lines, fences, index, indent);
248
- const productionHeaders = body.filter(line => /^\s*produces\b/.test(lines[line]));
249
- symbols.commands.push({
250
- name: commandMatch[1],
251
- properties: propertiesIn(lines, body.filter(line => lines[line].trim() !== 'validate csharp'), commandReserved),
252
- productionHeaders,
253
- produces: productionHeaders.flatMap(line => {
254
- const header = eventLines[line].trim();
255
- const inline = /^produces\s+event\b/.test(header);
256
- const conditional = /^produces\s+when\b/.test(header);
257
- const eventLine = conditional ? directBody(eventLines, eventFences, line, indentOf(eventLines[line]))[0] : line;
258
- if (eventLine === undefined) return [];
259
- const name = conditional ? eventLines[eventLine].trim() : header.match(inline ? /^produces\s+event\s+([A-Za-z_]\w*)(?:\s+generation\s+\d+)?\s*$/ : /^produces\s+([A-Z]\w*)\s*$/)?.[1];
260
- if (name === undefined || !/^[A-Za-z_]\w*$/.test(name)) return [];
261
- const children = directBody(eventLines, eventFences, eventLine, indentOf(eventLines[eventLine]));
262
- const targets = children.map(index => eventLines[index].trim().match(/^for(?:\s+(.*))?$/)).filter(match => match !== null);
263
- // Empty or repeated targets are uncertain, not implicit destinations.
264
- const target = targets.length === 0 ? undefined : targets.length === 1 ? targets[0][1] ?? '' : '';
265
- const mappings = children.flatMap(index => {
266
- const match = eventLines[index].trim().match(inline ? /^(@?[a-z_]\w*)\s+[\w.[\]?]+\s*=(?!=|>)\s*(.+)$/ : /^(@?[\w.]+)\s*=(?!=|>)\s*(.+)$/);
267
- return match === null ? [] : [{ name: match[1].replace(/^@/, ''), source: match[2], line: index }];
268
- });
269
- return [{ name, inline, conditional, line, target, mappings }];
270
- }),
271
- reads: body.filter((line) => !fences[line])
272
- .map((line) => ({ line, match: lines[line].match(readPattern) }))
273
- .filter((entry): entry is { line: number; match: RegExpMatchArray } => entry.match !== null)
274
- .map(({ line, match }) => ({
275
- view: match[1],
276
- ...(match[2] ? { alias: match[2] } : {}),
277
- ...(match[3] ? { by: match[3] } : {}),
278
- line,
279
- })),
280
- line: index,
281
- });
282
- continue;
283
- }
284
-
285
- // The return type shape is the compiler's, dots and all - QueryParser's
286
- // ^query\s+([A-Za-z_]\w*)\s*=>\s*(observable\s+)?([\w.]+(?:\[\])?\??)$. A narrower one here
287
- // silently drops the query from the symbol table, and with it every check and completion that
288
- // reads from it.
289
- const queryMatch = trimmed.match(/^query\s+(\w+)\s*=>\s*(?:observable\s+)?([\w.]+(?:\[\])?\??)\s*$/);
290
- if (queryMatch) {
291
- // The return type names a read model, which no construct declares — only the
292
- // 'by' and 'filter' parameters resolve against the document's own types.
293
- const parameters = collectBody(lines, fences, index, indent)
294
- .map((i) => ({ index: i, match: lines[i].match(queryParameterPattern) }))
295
- .filter(
296
- (entry): entry is { index: number; match: RegExpMatchArray } =>
297
- entry.match !== null,
298
- )
299
- .map(({ index: line, match }) => ({
300
- name: match[1],
301
- type: match[2],
302
- isIdentifier: false,
303
- line,
304
- }));
305
- symbols.queries.push({
306
- name: queryMatch[1],
307
- returnType: queryMatch[2],
308
- parameters,
309
- line: index,
310
- });
311
- continue;
312
- }
313
-
314
- const screenMatch = trimmed.match(/^screen\s+(\w+)\s*$/);
315
- if (screenMatch) {
316
- symbols.screens.push({ name: screenMatch[1], line: index });
317
- continue;
318
- }
319
-
320
- const triggerMatch = trimmed.match(/^trigger\s+(\w+)\s*$/);
321
- if (triggerMatch && indent === 0) {
322
- symbols.triggers.push({ name: triggerMatch[1], line: index });
323
- }
324
- }
325
-
326
- return symbols;
327
- }
328
-
329
- // The symbols of several documents as one - what an application spread over files declares. Lines refer to
330
- // the document each symbol came from, so the result names things; it does not locate them.
331
- export function mergeSymbols(...documents: DocumentSymbols[]): DocumentSymbols {
332
- return {
333
- imports: documents.flatMap((document) => document.imports),
334
- concepts: documents.flatMap((document) => document.concepts),
335
- types: documents.flatMap((document) => document.types),
336
- policies: documents.flatMap((document) => document.policies),
337
- events: documents.flatMap((document) => document.events),
338
- commands: documents.flatMap((document) => document.commands),
339
- queries: documents.flatMap((document) => document.queries),
340
- screens: documents.flatMap((document) => document.screens),
341
- triggers: documents.flatMap((document) => document.triggers),
342
- };
343
- }
344
-
345
- export function knownEventNames(symbols: DocumentSymbols): string[] {
346
- return [
347
- ...symbols.events.map((event) => event.name),
348
- ...symbols.imports.map((imported) => imported.shortName),
349
- ];
350
- }
351
-
352
- // The built-in host signals, which have no declaration to scan for because every application has them.
353
- export const builtInTriggerNames = ['Startup', 'Shutdown'];
354
-
355
- // What a reaction's `when` may name: an event, a declared trigger, or a host signal. The compiler resolves
356
- // the three in that order, and the editor offers them the same way rather than guessing which was meant.
357
- export function knownTriggerNames(symbols: DocumentSymbols): string[] {
358
- return [
359
- ...knownEventNames(symbols),
360
- ...symbols.triggers.map((trigger) => trigger.name),
361
- ...builtInTriggerNames,
362
- ];
363
- }
364
-
365
- // Everything a property type reference can resolve to — the primitives, the declared
366
- // concepts and types, and the short names of the imports.
367
- export function knownTypeNames(symbols: DocumentSymbols, primitives: readonly string[]): string[] {
368
- return [
369
- ...primitives,
370
- ...symbols.concepts.map((concept) => concept.name),
371
- ...symbols.types.map((type) => type.name),
372
- ...symbols.imports.map((imported) => imported.shortName),
373
- ];
374
- }
@@ -1,33 +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 } from 'monaco-editor';
5
-
6
- export const screenplayDarkThemeName = 'screenplay-dark';
7
-
8
- export const screenplayDark: editor.IStandaloneThemeData = {
9
- base: 'vs-dark',
10
- inherit: true,
11
- rules: [
12
- { token: 'keyword.play', foreground: 'C586C0' },
13
- { token: 'keyword.tag.play', foreground: '569CD6', fontStyle: 'italic' },
14
- { token: 'keyword.type.play', foreground: '4FC1FF', fontStyle: 'bold' },
15
- { token: 'type.play', foreground: '4EC9B0' },
16
- { token: 'type.identifier.play', foreground: '4EC9B0' },
17
- { token: 'identifier.play', foreground: '9CDCFE' },
18
- { token: 'annotation.play', foreground: 'DCDCAA' },
19
- { token: 'variable.predefined.play', foreground: 'D7BA7D' },
20
- { token: 'string.play', foreground: 'CE9178' },
21
- { token: 'string.link.play', foreground: 'CE9178', fontStyle: 'underline' },
22
- { token: 'string.invalid.play', foreground: 'F44747' },
23
- { token: 'string.quote.play', foreground: '6A9955' },
24
- { token: 'number.play', foreground: 'B5CEA8' },
25
- { token: 'number.float.play', foreground: 'B5CEA8' },
26
- { token: 'comment.play', foreground: '6A9955', fontStyle: 'italic' },
27
- { token: 'operator.play', foreground: 'D4D4D4' },
28
- { token: 'delimiter.play', foreground: 'CCCCCC' },
29
- ],
30
- colors: {
31
- 'editor.background': '#1E1E1E',
32
- },
33
- };
@@ -1,33 +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 } from 'monaco-editor';
5
-
6
- export const screenplayLightThemeName = 'screenplay-light';
7
-
8
- export const screenplayLight: editor.IStandaloneThemeData = {
9
- base: 'vs',
10
- inherit: true,
11
- rules: [
12
- { token: 'keyword.play', foreground: 'AF00DB' },
13
- { token: 'keyword.tag.play', foreground: '0000FF', fontStyle: 'italic' },
14
- { token: 'keyword.type.play', foreground: '0070C1', fontStyle: 'bold' },
15
- { token: 'type.play', foreground: '267F99' },
16
- { token: 'type.identifier.play', foreground: '267F99' },
17
- { token: 'identifier.play', foreground: '001080' },
18
- { token: 'annotation.play', foreground: '795E26' },
19
- { token: 'variable.predefined.play', foreground: 'B45309' },
20
- { token: 'string.play', foreground: 'A31515' },
21
- { token: 'string.link.play', foreground: 'A31515', fontStyle: 'underline' },
22
- { token: 'string.invalid.play', foreground: 'CD3131' },
23
- { token: 'string.quote.play', foreground: '008000' },
24
- { token: 'number.play', foreground: '098658' },
25
- { token: 'number.float.play', foreground: '098658' },
26
- { token: 'comment.play', foreground: '008000', fontStyle: 'italic' },
27
- { token: 'operator.play', foreground: '000000' },
28
- { token: 'delimiter.play', foreground: '000000' },
29
- ],
30
- colors: {
31
- 'editor.background': '#FFFFFF',
32
- },
33
- };