@cratis/screenplay-language 4.52.0 → 4.54.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.
- package/README.md +15 -0
- package/dist/TypeReferenceSymbol.d.ts +8 -0
- package/dist/TypeReferenceSymbol.d.ts.map +1 -0
- package/dist/bundles/chunk-GJX4NJYC.js +4836 -0
- package/dist/bundles/chunk-GJX4NJYC.js.map +7 -0
- package/dist/bundles/index.js +1417 -0
- package/dist/bundles/index.js.map +7 -0
- package/dist/bundles/sub-languages/capture/index.js +677 -0
- package/dist/bundles/sub-languages/capture/index.js.map +7 -0
- package/dist/bundles/sub-languages/projection/index.js +1647 -0
- package/dist/bundles/sub-languages/projection/index.js.map +7 -0
- package/dist/code-actions.d.ts +3 -0
- package/dist/code-actions.d.ts.map +1 -0
- package/dist/completion-items.d.ts +1 -0
- package/dist/completion-items.d.ts.map +1 -1
- package/dist/completion-planner.d.ts.map +1 -1
- package/dist/completions.d.ts.map +1 -1
- package/dist/diagnostic-codes.d.ts +3 -0
- package/dist/diagnostic-codes.d.ts.map +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/hover-content.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/keyword-docs.d.ts.map +1 -1
- package/dist/language.d.ts +1 -0
- package/dist/language.d.ts.map +1 -1
- package/dist/production-destinations.d.ts.map +1 -1
- package/dist/symbols.d.ts +4 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/validation.d.ts +1 -0
- package/dist/validation.d.ts.map +1 -1
- package/package.json +13 -9
- package/DestinationHint.ts +0 -8
- package/ProductionSymbol.ts +0 -11
- package/completion-items.ts +0 -261
- package/completion-planner.ts +0 -167
- package/completions.ts +0 -156
- package/diagnostic-codes.ts +0 -43
- package/diagnostics.ts +0 -55
- package/dist/DestinationHint.js +0 -4
- package/dist/DestinationHint.js.map +0 -1
- package/dist/ProductionSymbol.js +0 -4
- package/dist/ProductionSymbol.js.map +0 -1
- package/dist/completion-items.js +0 -228
- package/dist/completion-items.js.map +0 -1
- package/dist/completion-planner.js +0 -143
- package/dist/completion-planner.js.map +0 -1
- package/dist/completions.js +0 -101
- package/dist/completions.js.map +0 -1
- package/dist/diagnostic-codes.js +0 -41
- package/dist/diagnostic-codes.js.map +0 -1
- package/dist/diagnostics.js +0 -50
- package/dist/diagnostics.js.map +0 -1
- package/dist/document-context.js +0 -85
- package/dist/document-context.js.map +0 -1
- package/dist/event-analysis-source.js +0 -19
- package/dist/event-analysis-source.js.map +0 -1
- package/dist/event-context-catalog.js +0 -116
- package/dist/event-context-catalog.js.map +0 -1
- package/dist/event-context.js +0 -88
- package/dist/event-context.js.map +0 -1
- package/dist/file-imports.js +0 -58
- package/dist/file-imports.js.map +0 -1
- package/dist/file-references.js +0 -70
- package/dist/file-references.js.map +0 -1
- package/dist/hover-content.js +0 -98
- package/dist/hover-content.js.map +0 -1
- package/dist/hover.js +0 -15
- package/dist/hover.js.map +0 -1
- package/dist/index.js +0 -61
- package/dist/index.js.map +0 -1
- package/dist/inlay-hints.js +0 -15
- package/dist/inlay-hints.js.map +0 -1
- package/dist/inline-event-validation.js +0 -131
- package/dist/inline-event-validation.js.map +0 -1
- package/dist/keyword-docs.js +0 -148
- package/dist/keyword-docs.js.map +0 -1
- package/dist/language.js +0 -196
- package/dist/language.js.map +0 -1
- package/dist/production-destinations.js +0 -32
- package/dist/production-destinations.js.map +0 -1
- package/dist/sub-language-registry.js +0 -18
- package/dist/sub-language-registry.js.map +0 -1
- package/dist/sub-languages/capture/CompletionProvider.js +0 -332
- package/dist/sub-languages/capture/CompletionProvider.js.map +0 -1
- package/dist/sub-languages/capture/HoverProvider.js +0 -87
- package/dist/sub-languages/capture/HoverProvider.js.map +0 -1
- package/dist/sub-languages/capture/Validator.js +0 -72
- package/dist/sub-languages/capture/Validator.js.map +0 -1
- package/dist/sub-languages/capture/index.js +0 -58
- package/dist/sub-languages/capture/index.js.map +0 -1
- package/dist/sub-languages/capture/language.js +0 -160
- package/dist/sub-languages/capture/language.js.map +0 -1
- package/dist/sub-languages/cdl.js +0 -74
- package/dist/sub-languages/cdl.js.map +0 -1
- package/dist/sub-languages/pdl.js +0 -73
- package/dist/sub-languages/pdl.js.map +0 -1
- package/dist/sub-languages/projection/CodeActionProvider.js +0 -93
- package/dist/sub-languages/projection/CodeActionProvider.js.map +0 -1
- package/dist/sub-languages/projection/CompletionProvider.js +0 -595
- package/dist/sub-languages/projection/CompletionProvider.js.map +0 -1
- package/dist/sub-languages/projection/HoverProvider.js +0 -333
- package/dist/sub-languages/projection/HoverProvider.js.map +0 -1
- package/dist/sub-languages/projection/Validator.js +0 -388
- package/dist/sub-languages/projection/Validator.js.map +0 -1
- package/dist/sub-languages/projection/index.js +0 -160
- package/dist/sub-languages/projection/index.js.map +0 -1
- package/dist/sub-languages/projection/language.js +0 -171
- package/dist/sub-languages/projection/language.js.map +0 -1
- package/dist/symbols.js +0 -275
- package/dist/symbols.js.map +0 -1
- package/dist/themes/screenplay-dark.js +0 -30
- package/dist/themes/screenplay-dark.js.map +0 -1
- package/dist/themes/screenplay-light.js +0 -30
- package/dist/themes/screenplay-light.js.map +0 -1
- package/dist/tokens.js +0 -147
- package/dist/tokens.js.map +0 -1
- package/dist/validation.js +0 -248
- package/dist/validation.js.map +0 -1
- package/document-context.ts +0 -93
- package/event-analysis-source.ts +0 -18
- package/event-context-catalog.ts +0 -135
- package/event-context.ts +0 -119
- package/file-imports.ts +0 -70
- package/file-references.ts +0 -87
- package/for_documentContext/when_stripping_comments.ts +0 -32
- package/for_eventContext/when_resolving_generated_catalog_vectors.ts +0 -15
- package/for_eventGenerations/when_editing_event_generations.ts +0 -57
- package/for_fileImports/when_finding_file_imports.ts +0 -38
- package/for_fileReferences/when_recognizing_an_absolute_path/with_paths_of_every_shape.ts +0 -26
- package/for_fileReferences/when_scanning_a_document/inside_a_code_fence.ts +0 -26
- package/for_fileReferences/when_scanning_a_document/with_a_bare_file_keyword.ts +0 -19
- package/for_fileReferences/when_scanning_a_document/with_a_file_directive.ts +0 -30
- package/for_fileReferences/when_scanning_a_document/with_a_property_named_file.ts +0 -25
- package/for_fileReferences/when_scanning_a_document/with_a_trailing_comment.ts +0 -25
- package/for_fileReferences/when_scanning_a_document/with_directives_on_several_constructs.ts +0 -41
- package/for_importablePaths/when_listing_what_a_document_can_import.ts +0 -34
- package/for_inlineEvents/when_analyzing_many_inline_events.ts +0 -59
- package/for_inlineEvents/when_authoring_inline_events.ts +0 -149
- package/for_inlineEvents/when_completing_many_events.ts +0 -49
- package/for_inlineEvents/when_indexing_command_production_ownership.ts +0 -79
- package/for_planCompletions/when_completing_a_file_import.ts +0 -26
- package/for_planCompletions/when_completing_a_specification_query.ts +0 -24
- package/for_planCompletions/when_completing_a_specification_step.ts +0 -42
- package/for_planCompletions/when_completing_an_absent_read_model.ts +0 -14
- package/for_planCompletions/when_completing_reaction_reads.ts +0 -36
- package/for_projectionCompletionProvider/when_completing_an_event_context_path.ts +0 -102
- package/for_projectionHoverProvider/when_hovering_an_event_context_path.ts +0 -44
- package/for_projectionValidator/when_validating_a_projection_with_variants.ts +0 -128
- package/for_projectionValidator/when_validating_event_context_paths.ts +0 -31
- package/for_scanDocument/when_scanning_a_query/with_a_dotted_return_type.ts +0 -34
- package/for_scanDocument/when_scanning_aliased_reads.ts +0 -33
- package/for_scanDocument/when_scanning_many_commands.ts +0 -47
- package/for_tokens/when_highlighting_a_file_import.ts +0 -18
- package/for_tokens/when_highlighting_event_metadata.ts +0 -63
- package/for_tokens/when_highlighting_specification_steps.ts +0 -28
- package/for_validateLines/when_validating_a_document/with_a_problem_of_every_coded_kind.ts +0 -77
- package/for_validateLines/when_validating_a_document/with_an_unknown_policy.ts +0 -33
- package/for_validateLines/when_validating_a_file_placed_by_an_import/with_names_declared_in_other_files.ts +0 -43
- package/for_validateLines/when_validating_event_context_paths/in_a_projection.ts +0 -97
- package/for_validateLines/when_validating_file_imports/at_every_level.ts +0 -36
- package/for_validateLines/when_validating_production_destinations/with_an_available_identifier.ts +0 -120
- package/hover-content.ts +0 -117
- package/hover.ts +0 -23
- package/index.ts +0 -125
- package/inlay-hints.ts +0 -17
- package/inline-event-validation.ts +0 -115
- package/keyword-docs.ts +0 -152
- package/language.ts +0 -212
- package/production-destinations.ts +0 -32
- package/sub-language-registry.ts +0 -42
- package/sub-languages/capture/CompletionProvider.ts +0 -365
- package/sub-languages/capture/HoverProvider.ts +0 -99
- package/sub-languages/capture/Validator.ts +0 -97
- package/sub-languages/capture/index.ts +0 -72
- package/sub-languages/capture/language.ts +0 -176
- package/sub-languages/cdl.ts +0 -76
- package/sub-languages/pdl.ts +0 -75
- package/sub-languages/projection/CodeActionProvider.ts +0 -123
- package/sub-languages/projection/CompletionProvider.ts +0 -660
- package/sub-languages/projection/HoverProvider.ts +0 -377
- package/sub-languages/projection/Validator.ts +0 -441
- package/sub-languages/projection/index.ts +0 -223
- package/sub-languages/projection/language.ts +0 -193
- package/symbols.ts +0 -374
- package/themes/screenplay-dark.ts +0 -33
- package/themes/screenplay-light.ts +0 -33
- package/tokens.ts +0 -174
- package/validation.ts +0 -443
- package/vitest.setup.ts +0 -5
|
@@ -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 { describe, beforeEach, it } from 'vitest';
|
|
5
|
-
import { diagnosticCodes } from '../../diagnostic-codes';
|
|
6
|
-
import { ValidationIssue, validateLines } from '../../validation';
|
|
7
|
-
|
|
8
|
-
describe('when validating a document with an unknown policy', () => {
|
|
9
|
-
let issues: ValidationIssue[];
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
issues = validateLines([
|
|
13
|
-
'module Invoicing',
|
|
14
|
-
' feature Invoices',
|
|
15
|
-
' slice StateView Overdue',
|
|
16
|
-
' query Overdue => OverdueReadModel[]',
|
|
17
|
-
' authorize CanRead',
|
|
18
|
-
' or CanAlsoRead',
|
|
19
|
-
]);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should report the policy named on the authorize line', () => {
|
|
23
|
-
issues[0].should.include({ line: 4, code: diagnosticCodes.unknownPolicy });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should report the policy continued on the line below it', () => {
|
|
27
|
-
issues[1].should.include({ line: 5, code: diagnosticCodes.unknownPolicy });
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should report nothing else', () => {
|
|
31
|
-
issues.should.have.lengthOf(2);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -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
|
-
import { describe, beforeEach, it } from 'vitest';
|
|
5
|
-
import { mergeSymbols, scanDocument } from '../../symbols';
|
|
6
|
-
import { ValidationIssue, validateLines } from '../../validation';
|
|
7
|
-
|
|
8
|
-
// A file an import places in a feature holds slices at its top level, and the names it uses are declared in
|
|
9
|
-
// the other files of the application.
|
|
10
|
-
describe('when validating a file placed by an import with names declared in other files', () => {
|
|
11
|
-
let issues: ValidationIssue[];
|
|
12
|
-
let alone: ValidationIssue[];
|
|
13
|
-
const fragment = [
|
|
14
|
-
'slice StateChange PlaceOrder',
|
|
15
|
-
' command PlaceOrder',
|
|
16
|
-
' orderId OrderId identifier',
|
|
17
|
-
' customer Customer',
|
|
18
|
-
' authorize Staff',
|
|
19
|
-
' produces OrderPlaced',
|
|
20
|
-
' for orderId',
|
|
21
|
-
' reaction Notify',
|
|
22
|
-
' when OrderPlaced',
|
|
23
|
-
' produces CustomerNotified',
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
const application = mergeSymbols(
|
|
28
|
-
scanDocument(['concept OrderId : Uuid', 'policy Staff', ' require authenticated']),
|
|
29
|
-
scanDocument(['type Customer', ' name String', 'module Ordering', ' feature Orders', ' slice StateChange PlaceOrder', ' event OrderPlaced', ' note String']),
|
|
30
|
-
scanDocument(['import Customers.CustomerNotified']),
|
|
31
|
-
);
|
|
32
|
-
issues = validateLines(fragment, { application });
|
|
33
|
-
alone = validateLines(fragment);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should report nothing', () => {
|
|
37
|
-
issues.should.be.empty;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should report the names as unknown without the application', () => {
|
|
41
|
-
alone.map((issue) => issue.code).should.deep.equal(['PLAY0165', 'PLAY0165', 'PLAY0167', 'PLAY0166', 'PLAY0166']);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
@@ -1,97 +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 { diagnosticCodes } from '../../diagnostic-codes';
|
|
6
|
-
import { eventContextPaths } from '../../event-context';
|
|
7
|
-
import { ValidationIssue, validateLines } from '../../validation';
|
|
8
|
-
|
|
9
|
-
function validate(...mappings: string[]): ValidationIssue[] {
|
|
10
|
-
return validateLines([
|
|
11
|
-
'projection Statistics => StatisticsReadModel',
|
|
12
|
-
' from Happened',
|
|
13
|
-
...mappings.map((mapping) => ` ${mapping}`),
|
|
14
|
-
]);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
describe('when validating every event context path the catalog lists', () => {
|
|
18
|
-
let issues: ValidationIssue[];
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
issues = validate(
|
|
22
|
-
...eventContextPaths.map((path, index) => `value${index} = $eventContext.${path.path}`),
|
|
23
|
-
...eventContextPaths.map((path) => `count countBy.$eventContext.${path.path}`),
|
|
24
|
-
'week = $eventContext.occurred.Week()',
|
|
25
|
-
'type = $eventContext.EventType.Id',
|
|
26
|
-
);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should report nothing', () => {
|
|
30
|
-
issues.should.be.empty;
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe('when validating an unknown event context member', () => {
|
|
35
|
-
let issues: ValidationIssue[];
|
|
36
|
-
|
|
37
|
-
beforeEach(() => {
|
|
38
|
-
issues = validate('cause = $eventContext.causationId');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should warn with the compiler code', () => {
|
|
42
|
-
issues.map((issue) => [issue.code, issue.severity]).should.deep.equal([[diagnosticCodes.unknownEventContextMember, 'warning']]);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should squiggle the whole path', () => {
|
|
46
|
-
const [issue] = issues;
|
|
47
|
-
[issue.startColumn, issue.endColumn].should.deep.equal([13, 13 + '$eventContext.causationId'.length]);
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('when validating an unknown event context sub-path', () => {
|
|
52
|
-
let issues: ValidationIssue[];
|
|
53
|
-
|
|
54
|
-
beforeEach(() => {
|
|
55
|
-
issues = validate('week = $eventContext.occurred.week');
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should warn with the compiler code', () => {
|
|
59
|
-
issues.map((issue) => [issue.code, issue.severity]).should.deep.equal([[diagnosticCodes.unknownEventContextPath, 'warning']]);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('when validating a path below an event context collection', () => {
|
|
64
|
-
let issues: ValidationIssue[];
|
|
65
|
-
|
|
66
|
-
beforeEach(() => {
|
|
67
|
-
issues = validate('count byTag.$eventContext.tags.value');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('should report an error with the compiler code', () => {
|
|
71
|
-
issues.map((issue) => [issue.code, issue.severity]).should.deep.equal([[diagnosticCodes.eventContextPathBelowCollection, 'error']]);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe('when validating a dynamic key naming no event context member', () => {
|
|
76
|
-
let issues: ValidationIssue[];
|
|
77
|
-
|
|
78
|
-
beforeEach(() => {
|
|
79
|
-
issues = validate('count byNothing.$eventContext');
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('should report an error with the compiler code', () => {
|
|
83
|
-
issues.map((issue) => [issue.code, issue.severity]).should.deep.equal([[diagnosticCodes.missingEventContextPath, 'error']]);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('when validating a dynamic key naming another source', () => {
|
|
88
|
-
let issues: ValidationIssue[];
|
|
89
|
-
|
|
90
|
-
beforeEach(() => {
|
|
91
|
-
issues = validate('count byUser.$causedBy.subject');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('should warn with the compiler code', () => {
|
|
95
|
-
issues.map((issue) => [issue.code, issue.severity]).should.deep.equal([[diagnosticCodes.unresolvedDynamicKeySource, 'warning']]);
|
|
96
|
-
});
|
|
97
|
-
});
|
|
@@ -1,36 +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 { diagnosticCodes } from '../../diagnostic-codes';
|
|
6
|
-
import { ValidationIssue, validateLines } from '../../validation';
|
|
7
|
-
|
|
8
|
-
describe('when validating file imports at every level', () => {
|
|
9
|
-
let issues: ValidationIssue[];
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
issues = validateLines([
|
|
13
|
-
'import Customers.CustomerRegistered',
|
|
14
|
-
'import "**/*.play" // every document',
|
|
15
|
-
'import "Bad\\Path.play"',
|
|
16
|
-
'module Ordering',
|
|
17
|
-
' import "Orders/*.play"',
|
|
18
|
-
' import Customers.CustomerRegistered',
|
|
19
|
-
' feature Orders',
|
|
20
|
-
' import "Slices/**/*.play"',
|
|
21
|
-
' import "Unclosed',
|
|
22
|
-
]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should report the malformed and the qualified imports inside a body', () => {
|
|
26
|
-
issues.map((issue) => `${issue.code}@${issue.line}`).should.deep.equal([
|
|
27
|
-
`${diagnosticCodes.invalidFileImport}@2`,
|
|
28
|
-
`${diagnosticCodes.invalidFileImport}@5`,
|
|
29
|
-
`${diagnosticCodes.invalidFileImport}@8`,
|
|
30
|
-
]);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should span the whole import', () => {
|
|
34
|
-
issues[1].should.include({ startColumn: 3, endColumn: 3 + 'import Customers.CustomerRegistered'.length });
|
|
35
|
-
});
|
|
36
|
-
});
|
package/for_validateLines/when_validating_production_destinations/with_an_available_identifier.ts
DELETED
|
@@ -1,120 +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 { beforeEach, describe, it } from 'vitest';
|
|
5
|
-
import { diagnosticCodes } from '../../diagnostic-codes';
|
|
6
|
-
import { ValidationIssue, validateLines } from '../../validation';
|
|
7
|
-
|
|
8
|
-
const source = [
|
|
9
|
-
'module Projects',
|
|
10
|
-
' feature Registration',
|
|
11
|
-
' slice StateChange Register',
|
|
12
|
-
' command Register',
|
|
13
|
-
' projectId Uuid identifier',
|
|
14
|
-
' produces ProjectRegistered // omitted destination',
|
|
15
|
-
' name = name',
|
|
16
|
-
' produces ProjectUpdated',
|
|
17
|
-
' for projectId // explicit destination',
|
|
18
|
-
' produces when true == true',
|
|
19
|
-
' ProjectConditional',
|
|
20
|
-
' event ProjectRegistered',
|
|
21
|
-
' event ProjectUpdated',
|
|
22
|
-
' event ProjectConditional',
|
|
23
|
-
];
|
|
24
|
-
|
|
25
|
-
const destinations = (lines: string[]) => validateLines(lines).filter(issue => issue.code === diagnosticCodes.omittedProductionDestination);
|
|
26
|
-
|
|
27
|
-
describe('when validating production destinations with an available identifier', () => {
|
|
28
|
-
let issues: ValidationIssue[];
|
|
29
|
-
|
|
30
|
-
beforeEach(() => {
|
|
31
|
-
issues = destinations(source);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should advise only on the plain omitted destination', () => {
|
|
35
|
-
issues.map(issue => issue.line).should.deep.equal([5]);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should keep the advice informational', () => {
|
|
39
|
-
issues[0].severity.should.equal('information');
|
|
40
|
-
issues[0].message.should.contain('for projectId');
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should not advise without an identifier', () => {
|
|
44
|
-
destinations(source.map(line => line.replace(' identifier', ''))).should.have.lengthOf(0);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it.each(['Uuid?', 'Uuid[]', 'Uuid[]?'])('should not advise for a %s identifier', (type) => {
|
|
48
|
-
destinations(source.map(line => line.replace('projectId Uuid identifier', `projectId ${type} identifier`))).should.have.lengthOf(0);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it.each([
|
|
52
|
-
['command Register // explanation', 'projectId Uuid identifier'],
|
|
53
|
-
['command Register', 'projectId Uuid identifier // explanation'],
|
|
54
|
-
['command Register // explanation', 'projectId Uuid identifier // explanation'],
|
|
55
|
-
])('should discover identifiers despite trailing comments: %s; %s', (command, property) => {
|
|
56
|
-
destinations(source.map(line => line.replace('command Register', command).replace('projectId Uuid identifier', property)))
|
|
57
|
-
.map(issue => issue.line).should.deep.equal([5]);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it.each(['// outside', ' // beside the command', ' // beside the production'])(
|
|
61
|
-
'should skip comment-only ancestry lines: %s', (comment) => {
|
|
62
|
-
destinations([...source.slice(0, 5), comment, ...source.slice(5)])
|
|
63
|
-
.map(issue => issue.line).should.deep.equal([6]);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it.each(['description', 'handler', 'concurrency', 'validate', 'template', 'profile', 'when', 'identifier', 'sourceType', 'streamType'])(
|
|
67
|
-
'should follow command property rules for %s', (name) => {
|
|
68
|
-
const issues = destinations(source.map(line => line.replaceAll('projectId', name)));
|
|
69
|
-
issues.map(issue => issue.line).should.deep.equal([5]);
|
|
70
|
-
issues[0].message.should.contain(`for ${name}`);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should not treat a nested concurrency dimension as a command identifier', () => {
|
|
74
|
-
destinations([
|
|
75
|
-
...source.slice(0, 4),
|
|
76
|
-
' concurrency',
|
|
77
|
-
' sourceType Uuid identifier',
|
|
78
|
-
' produces ProjectRegistered',
|
|
79
|
-
' event ProjectRegistered',
|
|
80
|
-
]).should.have.lengthOf(0);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should not discover an identifier inside a fence', () => {
|
|
84
|
-
destinations([
|
|
85
|
-
...source.slice(0, 4),
|
|
86
|
-
' produces ProjectRegistered',
|
|
87
|
-
' validate',
|
|
88
|
-
' ```csharp',
|
|
89
|
-
' ghostId Uuid identifier',
|
|
90
|
-
' ```',
|
|
91
|
-
' event ProjectRegistered',
|
|
92
|
-
]).should.have.lengthOf(0);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('should not count fenced identifiers beside a real identifier', () => {
|
|
96
|
-
destinations([
|
|
97
|
-
...source.slice(0, 5),
|
|
98
|
-
' produces ProjectRegistered',
|
|
99
|
-
' validate',
|
|
100
|
-
' ```csharp',
|
|
101
|
-
' ghostId Uuid identifier',
|
|
102
|
-
' ```',
|
|
103
|
-
' event ProjectRegistered',
|
|
104
|
-
]).map(issue => issue.line).should.deep.equal([5]);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('should not advise on reaction productions', () => {
|
|
108
|
-
destinations(source.map(line => line.replace('command Register', 'reaction Register'))).should.have.lengthOf(0);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should ignore fenced code that looks like a production', () => {
|
|
112
|
-
destinations([
|
|
113
|
-
...source.slice(0, 5),
|
|
114
|
-
' handler',
|
|
115
|
-
' ```csharp',
|
|
116
|
-
' produces NotScreenplay',
|
|
117
|
-
' ```',
|
|
118
|
-
]).should.have.lengthOf(0);
|
|
119
|
-
});
|
|
120
|
-
});
|
package/hover-content.ts
DELETED
|
@@ -1,117 +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 } from './document-context';
|
|
5
|
-
import { directBody, scanDocument } from './symbols';
|
|
6
|
-
import { eventAnalysisSource } from './event-analysis-source';
|
|
7
|
-
import { getSubLanguage } from './sub-language-registry';
|
|
8
|
-
import { attributeDocs, contextVariableDocs, keywordDocs, specificationKeywordDocs } from './keyword-docs';
|
|
9
|
-
|
|
10
|
-
// Produces the hover markdown for a word at a position, without any editor
|
|
11
|
-
// dependency — the Monaco service and the VSCode extension share this content.
|
|
12
|
-
// Columns are 1-based, matching both editors' word-at-position APIs.
|
|
13
|
-
export function hoverContent(
|
|
14
|
-
lines: string[],
|
|
15
|
-
lineIndex: number,
|
|
16
|
-
word: string,
|
|
17
|
-
startColumn: number,
|
|
18
|
-
endColumn: number,
|
|
19
|
-
): string | null {
|
|
20
|
-
const fences = fenceMap(lines);
|
|
21
|
-
if (fences[lineIndex]) return null;
|
|
22
|
-
|
|
23
|
-
const line = lines[lineIndex] ?? '';
|
|
24
|
-
const before = line.charAt(startColumn - 2);
|
|
25
|
-
|
|
26
|
-
if (before === '@') {
|
|
27
|
-
const doc = attributeDocs[word];
|
|
28
|
-
if (doc) return doc;
|
|
29
|
-
}
|
|
30
|
-
if (before === '$' || before === '.') {
|
|
31
|
-
const variable = line.substring(0, endColumn - 1).match(/\$[\w.]*$/)?.[0];
|
|
32
|
-
if (variable) {
|
|
33
|
-
const doc =
|
|
34
|
-
contextVariableDocs[variable] ??
|
|
35
|
-
(variable.startsWith('$env') ? contextVariableDocs['$env'] : undefined);
|
|
36
|
-
if (doc) return doc;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const symbols = scanDocument(lines);
|
|
41
|
-
|
|
42
|
-
const concept = symbols.concepts.find((candidate) => candidate.name === word);
|
|
43
|
-
if (concept) {
|
|
44
|
-
const attributes = concept.attributes.length ? ` ${concept.attributes.join(' ')}` : '';
|
|
45
|
-
const values = concept.enumValues.length
|
|
46
|
-
? `\n\nValues: ${concept.enumValues.join(', ')}`
|
|
47
|
-
: '';
|
|
48
|
-
const reasons = Object.entries(concept.attributeReasons)
|
|
49
|
-
.map(([attribute, reason]) => `\n\n**@${attribute}** — ${reason}`)
|
|
50
|
-
.join('');
|
|
51
|
-
return `\`\`\`screenplay\nconcept ${concept.name} : ${concept.primitive}${attributes}\n\`\`\`${reasons}${values}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const type = symbols.types.find((candidate) => candidate.name === word);
|
|
55
|
-
if (type) {
|
|
56
|
-
const properties = type.properties
|
|
57
|
-
.map((property) => `${property.name} ${property.type}`)
|
|
58
|
-
.join('\n');
|
|
59
|
-
return `\`\`\`screenplay\ntype ${type.name}\n${properties}\n\`\`\``;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const policy = symbols.policies.find((candidate) => candidate.name === word);
|
|
63
|
-
if (policy) {
|
|
64
|
-
const body = policy.requires.length ? policy.requires.join('\n') : '(custom C#)';
|
|
65
|
-
return `\`\`\`screenplay\npolicy ${policy.name}\n${body}\n\`\`\``;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const event = symbols.events.find((candidate) => candidate.name === word && candidate.line === lineIndex) ??
|
|
69
|
-
symbols.events.filter((candidate) => candidate.name === word)
|
|
70
|
-
.sort((left, right) => (right.generation ?? 1) - (left.generation ?? 1))[0];
|
|
71
|
-
if (event) {
|
|
72
|
-
const properties = event.properties
|
|
73
|
-
.map((property) => `${property.name} ${property.type}`)
|
|
74
|
-
.join('\n');
|
|
75
|
-
return `\`\`\`screenplay\nevent ${event.name}${event.generation !== undefined ? ` generation ${event.generation}` : ''}\n${properties}\n\`\`\``;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const command = symbols.commands.find((candidate) => candidate.name === word);
|
|
79
|
-
if (command && command.properties.length > 0) {
|
|
80
|
-
const properties = command.properties
|
|
81
|
-
.map(
|
|
82
|
-
(property) =>
|
|
83
|
-
`${property.name} ${property.type}${property.isIdentifier ? ' identifier' : ''}`,
|
|
84
|
-
)
|
|
85
|
-
.join('\n');
|
|
86
|
-
return `\`\`\`screenplay\ncommand ${command.name}\n${properties}\n\`\`\``;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Sub-language keywords take precedence inside their construct.
|
|
90
|
-
const chain = enclosingChain(lines, fences, lineIndex, indentOf(line));
|
|
91
|
-
for (const construct of [line.trim().split(/\s+/)[0], ...chain]) {
|
|
92
|
-
const subLanguage = getSubLanguage(construct ?? '');
|
|
93
|
-
const doc = subLanguage?.hovers?.[word];
|
|
94
|
-
if (doc) return doc;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (word === 'reads' && (chain[0] === 'every' || chain[0] === 'at') && chain.includes('reaction')) {
|
|
98
|
-
return '**reads** — Declares a whole view this clock trigger consults: `reads <View>`. Clock triggers take no values, so `by` is unavailable.';
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const step = line.trim().match(/^(given|when|then)\s+(?:no\s+)?(\w+)/);
|
|
102
|
-
if (step && step[2] === word && chain[0] === 'specification' && specificationKeywordDocs[word]) {
|
|
103
|
-
return `**${word}** — ${specificationKeywordDocs[word]}`;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (word === 'id' || word === 'documentation') {
|
|
107
|
-
const source = eventAnalysisSource(lines);
|
|
108
|
-
const inEvent = symbols.events.some(event => directBody(source, fences, event.line, indentOf(source[event.line])).includes(lineIndex));
|
|
109
|
-
const directive = word === 'id' ? /^\s*id\s+"/.test(source[lineIndex]) : /^\s*documentation\s*$/.test(source[lineIndex]);
|
|
110
|
-
if (!inEvent || !directive || startColumn !== indentOf(line) + 1) return null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const keywordDoc = keywordDocs[word];
|
|
114
|
-
if (keywordDoc) return `**${word}** — ${keywordDoc}`;
|
|
115
|
-
|
|
116
|
-
return null;
|
|
117
|
-
}
|
package/hover.ts
DELETED
|
@@ -1,23 +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
|
-
import { hoverContent } from './hover-content';
|
|
6
|
-
|
|
7
|
-
export function createHoverProvider(): languages.HoverProvider {
|
|
8
|
-
return {
|
|
9
|
-
provideHover(model, position) {
|
|
10
|
-
const word = model.getWordAtPosition(position);
|
|
11
|
-
if (!word) return null;
|
|
12
|
-
|
|
13
|
-
const content = hoverContent(
|
|
14
|
-
model.getLinesContent(),
|
|
15
|
-
position.lineNumber - 1,
|
|
16
|
-
word.word,
|
|
17
|
-
word.startColumn,
|
|
18
|
-
word.endColumn,
|
|
19
|
-
);
|
|
20
|
-
return content ? { contents: [{ value: content }] } : null;
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
}
|
package/index.ts
DELETED
|
@@ -1,125 +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 {
|
|
5
|
-
Monaco,
|
|
6
|
-
languageConfiguration,
|
|
7
|
-
languageExtensionPoint,
|
|
8
|
-
languageId,
|
|
9
|
-
} from './language';
|
|
10
|
-
import { createTokensProvider } from './tokens';
|
|
11
|
-
import { CompletionOptions, createCompletionProvider } from './completions';
|
|
12
|
-
import { createHoverProvider } from './hover';
|
|
13
|
-
import { createInlayHintsProvider } from './inlay-hints';
|
|
14
|
-
import { attachDiagnostics } from './diagnostics';
|
|
15
|
-
import {
|
|
16
|
-
getSubLanguage,
|
|
17
|
-
getSubLanguages,
|
|
18
|
-
onSubLanguagesChanged,
|
|
19
|
-
registerSubLanguage,
|
|
20
|
-
} from './sub-language-registry';
|
|
21
|
-
import { pdl } from './sub-languages/pdl';
|
|
22
|
-
import { cdl } from './sub-languages/cdl';
|
|
23
|
-
import { screenplayDark, screenplayDarkThemeName } from './themes/screenplay-dark';
|
|
24
|
-
import { screenplayLight, screenplayLightThemeName } from './themes/screenplay-light';
|
|
25
|
-
|
|
26
|
-
const registeredInstances = new Set<Monaco>();
|
|
27
|
-
|
|
28
|
-
function applyTokensProvider(monaco: Monaco): void {
|
|
29
|
-
monaco.languages.setMonarchTokensProvider(languageId, createTokensProvider(getSubLanguages()));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Sub-languages registered after register() recompose the tokenizer on the fly.
|
|
33
|
-
onSubLanguagesChanged(() => registeredInstances.forEach(applyTokensProvider));
|
|
34
|
-
|
|
35
|
-
// Registers the built-in PDL and CDL sub-languages. Hosts that do not go through
|
|
36
|
-
// register() — such as the VSCode extension — call this before using the registry.
|
|
37
|
-
export function ensureBuiltInSubLanguages(): void {
|
|
38
|
-
if (!getSubLanguage('projection')) registerSubLanguage('projection', pdl);
|
|
39
|
-
if (!getSubLanguage('capture')) registerSubLanguage('capture', cdl);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// What a host can tell the language service beyond the models it holds.
|
|
43
|
-
export type LanguageServiceOptions = CompletionOptions;
|
|
44
|
-
|
|
45
|
-
export function register(monaco: Monaco, options: LanguageServiceOptions = {}): void {
|
|
46
|
-
if (registeredInstances.has(monaco)) return;
|
|
47
|
-
|
|
48
|
-
ensureBuiltInSubLanguages();
|
|
49
|
-
|
|
50
|
-
registeredInstances.add(monaco);
|
|
51
|
-
|
|
52
|
-
monaco.languages.register(languageExtensionPoint);
|
|
53
|
-
monaco.languages.setLanguageConfiguration(languageId, languageConfiguration);
|
|
54
|
-
applyTokensProvider(monaco);
|
|
55
|
-
monaco.languages.registerCompletionItemProvider(languageId, createCompletionProvider(monaco, options));
|
|
56
|
-
monaco.languages.registerHoverProvider(languageId, createHoverProvider());
|
|
57
|
-
monaco.languages.registerInlayHintsProvider(languageId, createInlayHintsProvider());
|
|
58
|
-
monaco.editor.defineTheme(screenplayDarkThemeName, screenplayDark);
|
|
59
|
-
monaco.editor.defineTheme(screenplayLightThemeName, screenplayLight);
|
|
60
|
-
attachDiagnostics(monaco);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export {
|
|
64
|
-
causedByProperties,
|
|
65
|
-
clauseKeywords,
|
|
66
|
-
codeBlockTags,
|
|
67
|
-
conceptAttributes,
|
|
68
|
-
constructKeywords,
|
|
69
|
-
contextRoots,
|
|
70
|
-
languageId,
|
|
71
|
-
primitiveTypes,
|
|
72
|
-
sliceTypes,
|
|
73
|
-
} from './language';
|
|
74
|
-
export type { Monaco } from './language';
|
|
75
|
-
export { getSubLanguage, getSubLanguages, registerSubLanguage } from './sub-language-registry';
|
|
76
|
-
export type {
|
|
77
|
-
MonarchTokenRules,
|
|
78
|
-
SubLanguage,
|
|
79
|
-
SubLanguageCompletion,
|
|
80
|
-
SubLanguageDefinition,
|
|
81
|
-
} from './sub-language-registry';
|
|
82
|
-
export { pdl } from './sub-languages/pdl';
|
|
83
|
-
export { cdl } from './sub-languages/cdl';
|
|
84
|
-
export { screenplayDarkThemeName } from './themes/screenplay-dark';
|
|
85
|
-
export { screenplayLightThemeName } from './themes/screenplay-light';
|
|
86
|
-
export { enclosingChain, fenceMap, firstWord, indentOf } from './document-context';
|
|
87
|
-
export {
|
|
88
|
-
fileReferenceKeyword,
|
|
89
|
-
fileReferenceOn,
|
|
90
|
-
fileReferences,
|
|
91
|
-
isAbsoluteFileReferencePath,
|
|
92
|
-
} from './file-references';
|
|
93
|
-
export type { FileReference } from './file-references';
|
|
94
|
-
export { fileImportOn, fileImports, importablePaths, isFileImportLine } from './file-imports';
|
|
95
|
-
export type { FileImport } from './file-imports';
|
|
96
|
-
export type { CompletionOptions } from './completions';
|
|
97
|
-
export { builtInTriggerNames, knownEventNames, knownTriggerNames, knownTypeNames, mergeSymbols, scanDocument } from './symbols';
|
|
98
|
-
export type {
|
|
99
|
-
CommandSymbol,
|
|
100
|
-
ConceptSymbol,
|
|
101
|
-
DocumentSymbols,
|
|
102
|
-
EventSymbol,
|
|
103
|
-
ImportSymbol,
|
|
104
|
-
NamedSymbol,
|
|
105
|
-
PolicySymbol,
|
|
106
|
-
PropertySymbol,
|
|
107
|
-
ReadSymbol,
|
|
108
|
-
QuerySymbol,
|
|
109
|
-
TypeSymbol,
|
|
110
|
-
} from './symbols';
|
|
111
|
-
export { attributeDocs, contextVariableDocs, keywordDocs, specificationKeywordDocs } from './keyword-docs';
|
|
112
|
-
export { eventContextMemberAt, eventContextMembers, eventContextMembersAfter, eventContextPaths, namesEventContextMember } from './event-context';
|
|
113
|
-
export type { EventContextMember, EventContextPath } from './event-context';
|
|
114
|
-
export { contextVariableItems, producesItems, specificationStepItems } from './completion-items';
|
|
115
|
-
export type { CompletionEntry } from './completion-items';
|
|
116
|
-
export { completionEntriesFor, planCompletions } from './completion-planner';
|
|
117
|
-
export type { CompletionPlan } from './completion-planner';
|
|
118
|
-
export { hoverContent } from './hover-content';
|
|
119
|
-
export { validateLines } from './validation';
|
|
120
|
-
export { destinationHints, productionDestinations } from './production-destinations';
|
|
121
|
-
export type { DestinationHint } from './DestinationHint';
|
|
122
|
-
export type { ProductionSymbol } from './ProductionSymbol';
|
|
123
|
-
export type { ValidationContext, ValidationIssue, ValidationSeverity } from './validation';
|
|
124
|
-
export { diagnosticCodes } from './diagnostic-codes';
|
|
125
|
-
export type { DiagnosticCode } from './diagnostic-codes';
|
package/inlay-hints.ts
DELETED
|
@@ -1,17 +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
|
-
import { destinationHints } from './production-destinations';
|
|
6
|
-
|
|
7
|
-
export function createInlayHintsProvider(): languages.InlayHintsProvider {
|
|
8
|
-
return {
|
|
9
|
-
provideInlayHints(model, range) {
|
|
10
|
-
const hints = destinationHints(model.getLinesContent()).filter(hint => hint.line + 1 >= range.startLineNumber && hint.line + 1 <= range.endLineNumber);
|
|
11
|
-
return {
|
|
12
|
-
hints: hints.map(hint => ({ position: { lineNumber: hint.line + 1, column: hint.column }, label: hint.label, paddingLeft: true })),
|
|
13
|
-
dispose() {},
|
|
14
|
-
};
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
}
|