Skip to content

Commit 1d5990a

Browse files
authored
Merge pull request #29 from lstreckeisen/CMI-60-FR-1.4-Autocomplete
FR1.4 Autocomplete
2 parents 636a620 + ed8eb4f commit 1d5990a

File tree

49 files changed

+2314
-256
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2314
-256
lines changed

docs/class_semantic_validation.puml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@ class ContextMapperDslValidationRegistry {
77
}
88

99
class ContextMapperDslValidator {
10-
+ checkContextMappingModel(ContextMappingModel, ValidationAcceptor)
11-
+ checkValue(Value, ValidationAcceptor)
10+
+ validate(AstNode, ValidationAcceptor)
1211
}
1312

1413
class ContextMapperValidationProviderRegistry {
14+
- _providers: Map<string, ContextMapperValidationProvider<AstNode>>
1515
+ get(AstNode): ContextMapperValidationProvider<AstNode>
1616
}
1717

1818
interface ContextMapperValidationProvider {
19-
+ supports(AstNode): boolean
2019
+ validate(T, ValidationAcceptor)
2120
}
2221

2322
ValidationRegistry <|-- ContextMapperDslValidationRegistry
2423
ContextMapperDslValidationRegistry --> ContextMapperDslValidator
24+
ContextMapperDslValidationRegistry --> ContextMapperValidationProviderRegistry
2525
ContextMapperDslValidator --> ContextMapperValidationProviderRegistry
2626
ContextMapperValidationProviderRegistry o-- "0..*" ContextMapperValidationProvider
2727
@enduml

src/language/ContextMapperDslModule.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ContextMapperDslValidationRegistry } from './validation/ContextMapperDs
1515
import { ContextMapperValidationProviderRegistry } from './validation/ContextMapperValidationProviderRegistry.js'
1616
import { ContextMapperDslScopeProvider } from './references/ContextMapperDslScopeProvider.js'
1717
import { ContextMapperDslFoldingRangeProvider } from './folding/ContextMapperDslFoldingRageProvider.js'
18+
import { ContextMapperDslScopeComputation } from './references/ContextMapperDslScopeComputation.js'
1819

1920
/**
2021
* Declaration of custom services - add your own service classes here.
@@ -45,14 +46,15 @@ const validationProviderRegistry = new ContextMapperValidationProviderRegistry()
4546
export const ContextMapperDslModule: Module<ContextMapperDslServices, ModuleType> = {
4647
validation: {
4748
ContextMapperDslValidator: () => new ContextMapperDslValidator(validationProviderRegistry),
48-
ValidationRegistry: (services) => new ContextMapperDslValidationRegistry(services)
49+
ValidationRegistry: (services) => new ContextMapperDslValidationRegistry(services, validationProviderRegistry)
4950
},
5051
lsp: {
5152
SemanticTokenProvider: (services) => new ContextMapperDslSemanticTokenProvider(services, semanticTokenProviderRegistry),
5253
FoldingRangeProvider: (services) => new ContextMapperDslFoldingRangeProvider(services)
5354
},
5455
references: {
55-
ScopeProvider: (services) => new ContextMapperDslScopeProvider(services)
56+
ScopeProvider: (services) => new ContextMapperDslScopeProvider(services),
57+
ScopeComputation: (services) => new ContextMapperDslScopeComputation(services)
5658
}
5759
}
5860

src/language/context-mapper-dsl.langium

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
1212

1313
entry ContextMappingModel:
1414
(
15-
(contextMaps+=ContextMap) |
15+
(contextMap+=ContextMap) |
1616
(boundedContexts+=BoundedContext) |
1717
(domains+=Domain) |
1818
(userRequirements+=UserRequirement) |
@@ -22,22 +22,20 @@ entry ContextMappingModel:
2222
;
2323

2424
/*
25-
In Langium, elements in unordered groups are optional by default.
26-
However, the usage of the ? cardinality is not allowed in unordered groups.
27-
Therefore, to create a rule with optional, unordered elements, one needs to omit the ? operator and combine them with the & operator.
28-
This behavior may change in the future.
29-
Also, unordered groups may cause unreadable parsing errors. To resolve that, unordered groups can be replaced with a (A | B | C)* rule and enforce non-repetition of elements with a validator.
25+
Unordered groups may cause unreadable parsing errors. To resolve that, unordered groups can be replaced with a (A | B | C)* rule and enforce non-repetition of elements with a validator.
3026
https://github.com/eclipse-langium/langium/discussions/1903
27+
Also, unordered groups cause issues with autocomplete.
28+
Therefore all unordered group rules had to be converted to the recommended workaround from above.
3129
*/
3230

3331
ContextMap:
3432
// {ContextMap} make sure there is always a context map
3533
'ContextMap' (name=ID)?
3634
OPEN
3735
(
38-
('type' ('=')? type=ContextMapType) &
39-
('state' ('=')? state=ContextMapState)
40-
)
36+
('type' ('=')? type+=ContextMapType) |
37+
('state' ('=')? state+=ContextMapState)
38+
)*
4139
('contains' boundedContexts+=[BoundedContext] ("," boundedContexts+=[BoundedContext])*)*
4240
relationships+=Relationship*
4341
CLOSE
@@ -46,22 +44,22 @@ ContextMap:
4644
BoundedContext:
4745
'BoundedContext' name=ID (
4846
(
49-
('implements' (implementedDomainParts+=[DomainPart]) ("," implementedDomainParts+=[DomainPart])*) &
50-
('realizes' (realizedBoundedContexts+=[BoundedContext]) ("," realizedBoundedContexts+=[BoundedContext])*) &
51-
('refines' refinedBoundedContext=[BoundedContext])
52-
)
47+
('implements' (implementedDomainParts+=[DomainPart]) ("," implementedDomainParts+=[DomainPart])*) |
48+
('realizes' (realizedBoundedContexts+=[BoundedContext]) ("," realizedBoundedContexts+=[BoundedContext])*) |
49+
('refines' refinedBoundedContext+=[BoundedContext])
50+
)*
5351
)
5452
(
5553
OPEN
5654
(
57-
('domainVisionStatement' ('=')? domainVisionStatement=STRING) &
58-
('type' ('=')? type=BoundedContextType) &
59-
(('responsibilities' ('=')? responsibilities+=STRING) ("," responsibilities+=STRING)*) &
60-
('implementationTechnology' ('=')? implementationTechnology=STRING) &
61-
('knowledgeLevel' ('=')? knowledgeLevel=KnowledgeLevel) &
62-
('businessModel' ('=')? businessModel=STRING) &
63-
('evolution' ('=')? evolution=Evolution)
64-
)
55+
('domainVisionStatement' ('=')? domainVisionStatement+=STRING) |
56+
('type' ('=')? type+=BoundedContextType) |
57+
(('responsibilities' ('=')? responsibilities+=STRING) ("," responsibilities+=STRING)*) |
58+
('implementationTechnology' ('=')? implementationTechnology+=STRING) |
59+
('knowledgeLevel' ('=')? knowledgeLevel+=KnowledgeLevel) |
60+
('businessModel' ('=')? businessModel+=STRING) |
61+
('evolution' ('=')? evolution+=Evolution)
62+
)*
6563
(
6664
(
6765
modules+=SculptorModule |
@@ -91,9 +89,9 @@ Subdomain:
9189
(
9290
OPEN
9391
(
94-
('type' ('=')? type=SubDomainType) &
95-
('domainVisionStatement' ('=')? domainVisionStatement=STRING)
96-
)
92+
('type' ('=')? type+=SubDomainType) |
93+
('domainVisionStatement' ('=')? domainVisionStatement+=STRING)
94+
)*
9795
CLOSE
9896
)?
9997
;
@@ -147,10 +145,10 @@ UpstreamDownstreamRelationship:
147145
(':' name=ID)?
148146
(OPEN
149147
(
150-
('implementationTechnology' ('=')? implementationTechnology=STRING) &
151-
(('exposedAggregates' ('=')? upstreamExposedAggregates+=[Aggregate]) ("," upstreamExposedAggregates+=[Aggregate])*) &
152-
('downstreamRights' ('=')? downstreamGovernanceRights=DownstreamGovernanceRights)
153-
)
148+
('implementationTechnology' ('=')? implementationTechnology+=STRING) |
149+
(('exposedAggregates' ('=')? upstreamExposedAggregates+=[Aggregate]) ("," upstreamExposedAggregates+=[Aggregate])*) |
150+
('downstreamRights' ('=')? downstreamGovernanceRights+=DownstreamGovernanceRights)
151+
)*
154152
CLOSE)?
155153
)
156154
;
@@ -166,10 +164,10 @@ CustomerSupplierRelationship:
166164
(':' name=ID)?
167165
(OPEN
168166
(
169-
('implementationTechnology' ('=')? implementationTechnology=STRING) &
170-
(('exposedAggregates' ('=')? upstreamExposedAggregates+=[Aggregate]) ("," upstreamExposedAggregates+=[Aggregate])*) &
171-
('downstreamRights' ('=')? downstreamGovernanceRights=DownstreamGovernanceRights)
172-
)
167+
('implementationTechnology' ('=')? implementationTechnology+=STRING) |
168+
(('exposedAggregates' ('=')? upstreamExposedAggregates+=[Aggregate]) ("," upstreamExposedAggregates+=[Aggregate])*) |
169+
('downstreamRights' ('=')? downstreamGovernanceRights+=DownstreamGovernanceRights)
170+
)*
173171
CLOSE)?
174172
)
175173
;
@@ -178,23 +176,21 @@ Aggregate:
178176
(doc=STRING)?
179177
"Aggregate" name=ID (OPEN
180178
(
181-
(('responsibilities' ('=')? responsibilities+=STRING) ("," responsibilities+=STRING)*) &
182-
(
183-
(('useCases' ('=')? useCases+=[UseCase]) ("," useCases+=[UseCase])*) |
184-
(('userStories' ('=')? userStories+=[UserStory]) ("," userStories+=[UserStory])*) |
185-
((('features' | 'userRequirements') ('=')? userRequirements+=[UserRequirement]) ("," userRequirements+=[UserRequirement])*)
186-
) &
187-
('owner' ('=')? owner=[BoundedContext]) &
188-
('knowledgeLevel' ('=')? knowledgeLevel=KnowledgeLevel) &
189-
(('likelihoodForChange' | 'structuralVolatility') ('=')? likelihoodForChange=Volatility) &
190-
('contentVolatility' ('=')? contentVolatility=Volatility) &
191-
('availabilityCriticality' ('=')? availabilityCriticality=Criticality) &
192-
('consistencyCriticality' ('=')? consistencyCriticality=Criticality) &
193-
('storageSimilarity' ('=')? storageSimilarity=Similarity) &
194-
('securityCriticality' ('=')? securityCriticality=Criticality) &
195-
('securityZone' ('=')? securityZone=STRING) &
196-
('securityAccessGroup' ('=')? securityAccessGroup=STRING)
197-
)
179+
(('responsibilities' ('=')? responsibilities+=STRING) ("," responsibilities+=STRING)*) |
180+
(('useCases' ('=')? useCases+=[UseCase]) ("," useCases+=[UseCase])*) |
181+
(('userStories' ('=')? userStories+=[UserStory]) ("," userStories+=[UserStory])*) |
182+
((('features' | 'userRequirements') ('=')? userRequirements+=[UserRequirement]) ("," userRequirements+=[UserRequirement])*) |
183+
('owner' ('=')? owner+=[BoundedContext]) |
184+
('knowledgeLevel' ('=')? knowledgeLevel+=KnowledgeLevel) |
185+
(('likelihoodForChange' | 'structuralVolatility') ('=')? likelihoodForChange+=Volatility) |
186+
('contentVolatility' ('=')? contentVolatility+=Volatility) |
187+
('availabilityCriticality' ('=')? availabilityCriticality+=Criticality) |
188+
('consistencyCriticality' ('=')? consistencyCriticality+=Criticality) |
189+
('storageSimilarity' ('=')? storageSimilarity+=Similarity) |
190+
('securityCriticality' ('=')? securityCriticality+=Criticality) |
191+
('securityZone' ('=')? securityZone+=STRING) |
192+
('securityAccessGroup' ('=')? securityAccessGroup+=STRING)
193+
)*
198194
CLOSE)?
199195
;
200196

@@ -205,13 +201,13 @@ UserRequirement:
205201
UseCase:
206202
'UseCase' name=ID (OPEN
207203
(
208-
('actor' ('=')? role=STRING) &
209-
('secondaryActors' ('=')? secondaryActors+=STRING ("," secondaryActors+=STRING)*) &
210-
('interactions' ('=')? features+=Feature ("," features+=Feature)*) &
211-
('benefit' ('=')? benefit=STRING) &
212-
('scope' ('=')? scope=STRING) &
213-
('level' ('=')? level=STRING)
214-
)
204+
('actor' ('=')? role+=STRING) |
205+
('secondaryActors' ('=')? secondaryActors+=STRING ("," secondaryActors+=STRING)*) |
206+
('interactions' ('=')? features+=Feature ("," features+=Feature)*) |
207+
('benefit' ('=')? benefit+=STRING) |
208+
('scope' ('=')? scope+=STRING) |
209+
('level' ('=')? level+=STRING)
210+
)*
215211
CLOSE)?
216212
;
217213

@@ -247,10 +243,10 @@ SculptorModule:
247243
'Module' name=ID (
248244
OPEN
249245
(
250-
(external?='external') &
251-
('basePackage' '=' basePackage=JavaIdentifier) &
252-
('hint' '=' hint=STRING)
253-
)
246+
(external+='external') |
247+
('basePackage' '=' basePackage+=JavaIdentifier) |
248+
('hint' '=' hint+=STRING)
249+
)*
254250
(
255251
(aggregates+=Aggregate)
256252
)*
@@ -286,10 +282,10 @@ StakeholderGroup:
286282
Stakeholder:
287283
'Stakeholder' name=ID (OPEN
288284
(
289-
('influence' ('=')? influence=INFLUENCE) &
290-
('interest' ('=')? interest=INTEREST) &
291-
('description' ('=')? description=STRING)
292-
)
285+
('influence' ('=')? influence+=INFLUENCE) |
286+
('interest' ('=')? interest+=INTEREST) |
287+
('description' ('=')? description+=STRING)
288+
)*
293289
CLOSE)?
294290
;
295291

@@ -334,10 +330,10 @@ Value:
334330
ValueElicitation:
335331
('Stakeholder'|'Stakeholders') stakeholder=[AbstractStakeholder] (OPEN
336332
(
337-
('priority' ('=')? priority=PRIORITY) &
338-
('impact' ('=')? impact=IMPACT) &
333+
('priority' ('=')? priority+=PRIORITY) |
334+
('impact' ('=')? impact+=IMPACT) |
339335
('consequences' (consequences+=Consequence)+)
340-
)
336+
)*
341337
CLOSE)?
342338
;
343339

@@ -347,9 +343,9 @@ ValueEpic:
347343
(
348344
'As a' stakeholder=[AbstractStakeholder] 'I value' value=STRING 'as demonstrated in'
349345
(
350-
('realization of' realizedValues+=STRING)+ &
346+
('realization of' realizedValues+=STRING)+ |
351347
('reduction of' reducedValues+=STRING)+
352-
)
348+
)*
353349
)
354350
CLOSE)?
355351
;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { AstNode, AstNodeDescription, DefaultScopeComputation, LangiumDocument } from 'langium'
2+
import { CancellationToken } from 'vscode-languageserver'
3+
4+
export class ContextMapperDslScopeComputation extends DefaultScopeComputation {
5+
/*
6+
For the time being imports aren't supported yet.
7+
By default, Langium adds top-level elements to the global scope.
8+
Without imports, this behavior is wrong and therefore no nodes must be exported here.
9+
*/
10+
override computeExportsForNode (
11+
_parentNode: AstNode,
12+
_document: LangiumDocument,
13+
_children?: (root: AstNode) => Iterable<AstNode>,
14+
_cancelToken?: CancellationToken
15+
): Promise<AstNodeDescription[]> {
16+
return Promise.resolve([])
17+
}
18+
}
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import { type ValidationChecks, ValidationRegistry } from 'langium'
22
import { ContextMapperDslServices } from '../ContextMapperDslModule.js'
3-
import type { ContextMapperDslAstType } from '../generated/ast.js'
3+
import { ContextMapperDslAstType } from '../generated/ast.js'
4+
import { ContextMapperValidationProviderRegistry } from './ContextMapperValidationProviderRegistry.js'
45

56
export class ContextMapperDslValidationRegistry extends ValidationRegistry {
6-
constructor (services: ContextMapperDslServices) {
7+
constructor (services: ContextMapperDslServices, validationProviderRegistry: ContextMapperValidationProviderRegistry) {
78
super(services)
89
const validator = services.validation.ContextMapperDslValidator
9-
const checks: ValidationChecks<ContextMapperDslAstType> = {
10-
ContextMappingModel: validator.checkContextMappingModel,
11-
Value: validator.checkValue
12-
}
10+
11+
const typesToValidate = validationProviderRegistry.getRegisteredTypes()
12+
13+
// dynamically set validator for all grammar elements
14+
const checks: ValidationChecks<ContextMapperDslAstType> = Object.fromEntries(
15+
typesToValidate.map(type => [type, validator.validate])
16+
)
17+
1318
super.register(checks, validator)
1419
}
1520
}
Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { ValidationAcceptor } from 'langium'
2-
import type { ContextMappingModel, Value } from '../generated/ast.js'
1+
import { AstNode, ValidationAcceptor } from 'langium'
32
import { ContextMapperValidationProviderRegistry } from './ContextMapperValidationProviderRegistry.js'
43

54
export class ContextMapperDslValidator {
@@ -9,11 +8,7 @@ export class ContextMapperDslValidator {
98
this._registry = contextMapperValidationProviderRegistry
109
}
1110

12-
checkContextMappingModel (model: ContextMappingModel, acceptor: ValidationAcceptor) {
13-
this._registry.get(model)?.validate(model, acceptor)
14-
}
15-
16-
checkValue (value: Value, acceptor: ValidationAcceptor) {
17-
this._registry.get(value)?.validate(value, acceptor)
11+
validate (node: AstNode, acceptor: ValidationAcceptor) {
12+
this._registry.get(node)?.validate(node, acceptor)
1813
}
1914
}
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { AstNode, ValidationAcceptor } from 'langium'
22

33
export interface ContextMapperValidationProvider<T extends AstNode> {
4-
supports(node: AstNode): node is T
54
validate (node: T, acceptor: ValidationAcceptor): void
65
}

0 commit comments

Comments
 (0)