componentsjs 5.0.0-beta.2 → 5.0.0-beta.3
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/CHANGELOG.md +24 -0
- package/README.md +16 -0
- package/components/context.jsonld +13 -0
- package/lib/ComponentsManager.js +3 -5
- package/lib/loading/ComponentRegistryFinalizer.js +7 -1
- package/lib/preprocess/ConfigPreprocessorComponent.js +9 -13
- package/lib/preprocess/GenericsContext.d.ts +49 -5
- package/lib/preprocess/GenericsContext.js +278 -15
- package/lib/preprocess/ParameterHandler.d.ts +2 -0
- package/lib/preprocess/ParameterHandler.js +1 -1
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.d.ts +30 -10
- package/lib/preprocess/parameterproperty/ParameterPropertyHandlerRange.js +334 -118
- package/lib/util/ErrorResourcesContext.d.ts +11 -14
- package/lib/util/ErrorResourcesContext.js +44 -22
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
|
|
4
|
+
<a name="v5.0.0-beta.3"></a>
|
|
5
|
+
## [v5.0.0-beta.3](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v5.0.0-beta.2...v5.0.0-beta.3) - 2022-01-17
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
* [Add support for wildcard parameter ranges](https://github.com/LinkedSoftwareDependencies/Components.js/commit/83238a9fa08877f29326be562d7d3d5fff860c69)
|
|
9
|
+
* Improve error reporting:
|
|
10
|
+
* [Add causes for param check failures in error messages](https://github.com/LinkedSoftwareDependencies/Components.js/commit/9be1fd0899ffb8a77ea99e5fb86e661526ef6d1a)
|
|
11
|
+
* [Improve error message on invalid generic type instantiations](https://github.com/LinkedSoftwareDependencies/Components.js/commit/6ecb9798eeb84f09fece68b3a47454fa8c857ba4)
|
|
12
|
+
* [Move error context to error state file](https://github.com/LinkedSoftwareDependencies/Components.js/commit/dbf26e072bdc63168814ef4d503777efaf4745eb)
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
* Resolve several issues related to generics:
|
|
16
|
+
* [Throw error on invalid ParameterRangeGenericComponent](https://github.com/LinkedSoftwareDependencies/Components.js/commit/c692ab6175ce466fb32fbe38b973644e2601b2e6)
|
|
17
|
+
* [Fix generic components not accepting specific types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/c7739182fddcb92d46a86fe3e33d6e29fd1134b6)
|
|
18
|
+
* [Support generic type instantiation during component extension](https://github.com/LinkedSoftwareDependencies/Components.js/commit/98f70e350cc3f9bf8a4ea632db546f74624ddda7)
|
|
19
|
+
* [Support generic components in params with fixed generics](https://github.com/LinkedSoftwareDependencies/Components.js/commit/d8b30972e1306e9fe9db391d4693aa6000917e60)
|
|
20
|
+
* [Use GenericComponentExtension to refer to wrapped generic comp extensions](https://github.com/LinkedSoftwareDependencies/Components.js/commit/239895accfdb7f09a7ac8454928bd3e0be5e5f15)
|
|
21
|
+
* [Fix invalid range display with multiple generics](https://github.com/LinkedSoftwareDependencies/Components.js/commit/b98baf0bcf4546b60299ae548f929693345292bc)
|
|
22
|
+
* [Handle range merging if left or right is union](https://github.com/LinkedSoftwareDependencies/Components.js/commit/637e140106691b95f0f546cf88eb39f3f80dc61d)
|
|
23
|
+
* [Handle sub-types when merging param ranges](https://github.com/LinkedSoftwareDependencies/Components.js/commit/43290525b2e244f5fbb6d5f344760b863329c31b)
|
|
24
|
+
* [Allow merging of generic component param types](https://github.com/LinkedSoftwareDependencies/Components.js/commit/ee8de7d9b8d18bf6968a17078e493946e5fca8cd)
|
|
25
|
+
* [Allow param range merging with generic components](https://github.com/LinkedSoftwareDependencies/Components.js/commit/bcea7dcff288ce7068ee244c49c12134208c89da)
|
|
26
|
+
* [Fix generics crash when doing repeated param type checking](https://github.com/LinkedSoftwareDependencies/Components.js/commit/237572cb8a9c546b098582041ccd7a457b41aecd)
|
|
27
|
+
|
|
4
28
|
<a name="v5.0.0-beta.2"></a>
|
|
5
29
|
## [v5.0.0-beta.2](https://github.com/LinkedSoftwareDependencies/Components.js/compare/v5.0.0-beta.1...v5.0.0-beta.2) - 2021-12-09
|
|
6
30
|
|
package/README.md
CHANGED
|
@@ -202,6 +202,22 @@ const myInstance = await manager.instantiate('http://example.org/myInstance');
|
|
|
202
202
|
[RDF]: https://www.w3.org/RDF/
|
|
203
203
|
[JSON-LD]: https://json-ld.org/
|
|
204
204
|
|
|
205
|
+
## Cite
|
|
206
|
+
|
|
207
|
+
If you are using or extending Components.js as part of a scientific publication,
|
|
208
|
+
we would appreciate a citation of our [article](https://linkedsoftwaredependencies.github.io/Article-System-Components/).
|
|
209
|
+
|
|
210
|
+
```bibtex
|
|
211
|
+
@article{taelman_swj_componentsjs_2022,
|
|
212
|
+
author = {Taelman, Ruben and Van Herwegen, Joachim and Vander Sande, Miel and Verborgh, Ruben},
|
|
213
|
+
title = {Components.js: Semantic Dependency Injection},
|
|
214
|
+
journal = {Semantic Web Journal},
|
|
215
|
+
year = {2022},
|
|
216
|
+
month = jan,
|
|
217
|
+
url = {https://linkedsoftwaredependencies.github.io/Article-System-Components/}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
205
221
|
## License
|
|
206
222
|
Components.js is written by [Ruben Taelman](http://www.rubensworks.net/).
|
|
207
223
|
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
"@context": {
|
|
3
3
|
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
4
4
|
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
|
5
|
+
"type": {
|
|
6
|
+
"@id": "rdf:type"
|
|
7
|
+
},
|
|
5
8
|
"types": {
|
|
6
9
|
"@id": "rdf:type"
|
|
7
10
|
},
|
|
@@ -77,6 +80,9 @@
|
|
|
77
80
|
"ParameterRangeUndefined": {
|
|
78
81
|
"@id": "oo:ParameterRangeUndefined"
|
|
79
82
|
},
|
|
83
|
+
"ParameterRangeWildcard": {
|
|
84
|
+
"@id": "oo:ParameterRangeWildcard"
|
|
85
|
+
},
|
|
80
86
|
"ParameterRangeArray": {
|
|
81
87
|
"@id": "oo:ParameterRangeArray"
|
|
82
88
|
},
|
|
@@ -116,6 +122,10 @@
|
|
|
116
122
|
"ParameterRangeGenericComponent": {
|
|
117
123
|
"@id": "oo:ParameterRangeGenericComponent"
|
|
118
124
|
},
|
|
125
|
+
"genericTypeInstancesComponentScope": {
|
|
126
|
+
"@id": "oo:genericTypeInstancesComponentScope",
|
|
127
|
+
"@type": "@id"
|
|
128
|
+
},
|
|
119
129
|
"genericTypeInstances": {
|
|
120
130
|
"@id": "oo:genericTypeInstance",
|
|
121
131
|
"@type": "@id"
|
|
@@ -131,6 +141,9 @@
|
|
|
131
141
|
"@id": "oo:parameterRangeGenericBindings",
|
|
132
142
|
"@type": "@id"
|
|
133
143
|
},
|
|
144
|
+
"GenericComponentExtension": {
|
|
145
|
+
"@id": "oo:GenericComponentExtension"
|
|
146
|
+
},
|
|
134
147
|
|
|
135
148
|
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
|
|
136
149
|
"comment": {
|
package/lib/ComponentsManager.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ComponentsManager = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const ComponentsManagerBuilder_1 = require("./loading/ComponentsManagerBuilder");
|
|
6
|
+
const ErrorResourcesContext_1 = require("./util/ErrorResourcesContext");
|
|
6
7
|
/**
|
|
7
8
|
* A components manager can instantiate components.
|
|
8
9
|
* This manager should be created using {@link ComponentsManager.build}.
|
|
@@ -51,17 +52,14 @@ class ComponentsManager {
|
|
|
51
52
|
*/
|
|
52
53
|
generateErrorLog(error) {
|
|
53
54
|
if (this.dumpErrorState) {
|
|
54
|
-
const contents = JSON.stringify({
|
|
55
|
-
componentTypes: Object.keys(this.componentResources),
|
|
56
|
-
moduleState: {
|
|
55
|
+
const contents = JSON.stringify(Object.assign(Object.assign({}, error instanceof ErrorResourcesContext_1.ErrorResourcesContext ? error.exportContext() : {}), { componentTypes: Object.keys(this.componentResources), moduleState: {
|
|
57
56
|
mainModulePath: this.moduleState.mainModulePath,
|
|
58
57
|
componentModules: this.moduleState.componentModules,
|
|
59
58
|
importPaths: this.moduleState.importPaths,
|
|
60
59
|
contexts: this.moduleState.contexts,
|
|
61
60
|
nodeModuleImportPaths: this.moduleState.nodeModuleImportPaths,
|
|
62
61
|
nodeModulePaths: this.moduleState.nodeModulePaths,
|
|
63
|
-
},
|
|
64
|
-
}, null, ' ');
|
|
62
|
+
} }), null, ' ');
|
|
65
63
|
fs.writeFileSync('componentsjs-error-state.json', contents, 'utf8');
|
|
66
64
|
this.logger.error(`Detected fatal error. Generated 'componentsjs-error-state.json' with more information.`);
|
|
67
65
|
}
|
|
@@ -41,7 +41,13 @@ class ComponentRegistryFinalizer {
|
|
|
41
41
|
* @param superComponents The components to inherit from.
|
|
42
42
|
*/
|
|
43
43
|
inheritParameters(component, superComponents) {
|
|
44
|
-
|
|
44
|
+
var _a;
|
|
45
|
+
for (let superComponent of superComponents) {
|
|
46
|
+
// Check if the super component is wrapped in a generic component instantiation
|
|
47
|
+
if (((_a = superComponent.property.type) === null || _a === void 0 ? void 0 : _a.value) === this.objectLoader.contextResolved
|
|
48
|
+
.expandTerm('oo:GenericComponentExtension')) {
|
|
49
|
+
superComponent = superComponent.property.component;
|
|
50
|
+
}
|
|
45
51
|
this.componentRegistry.requireValidComponent(superComponent, component);
|
|
46
52
|
for (const parameter of superComponent.properties.parameters) {
|
|
47
53
|
if (!component.properties.parameters.includes(parameter)) {
|
|
@@ -89,20 +89,16 @@ class ConfigPreprocessorComponent {
|
|
|
89
89
|
return configRaw;
|
|
90
90
|
}
|
|
91
91
|
createGenericsContext(handleResponse, config) {
|
|
92
|
+
// Create a new generics context for the component's generic type parameters
|
|
92
93
|
const genericsContext = new GenericsContext_1.GenericsContext(this.objectLoader, handleResponse.component.properties.genericTypeParameters);
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
for (const [i, genericTypeInstance] of config.properties.genericTypeInstances.entries()) {
|
|
102
|
-
// Remap generic type IRI to inner generic type IRI
|
|
103
|
-
const genericTypeIdInner = genericTypesInner[i].value;
|
|
104
|
-
genericsContext.bindings[genericTypeIdInner] = genericTypeInstance.properties.parameterRangeGenericBindings;
|
|
105
|
-
genericsContext.genericTypeIds[genericTypeIdInner] = true;
|
|
94
|
+
// If the config has a genericTypeInstancesComponentScope, it will also have genericTypeInstances.
|
|
95
|
+
// In that case, we bind these instances to the component's generic type parameters within the context.
|
|
96
|
+
// (these values may have been set during generic param type-checking in
|
|
97
|
+
// ParameterPropertyHandlerRange#hasParamValueValidType)
|
|
98
|
+
if (config.property.genericTypeInstancesComponentScope &&
|
|
99
|
+
handleResponse.component.value === config.property.genericTypeInstancesComponentScope.value) {
|
|
100
|
+
genericsContext.bindComponentGenericTypes(handleResponse.component, config.properties.genericTypeInstances, { config }, (subType, superType) => this.parameterHandler.parameterPropertyHandlerRange
|
|
101
|
+
.hasType(subType, superType, genericsContext, config.property.genericTypeInstancesComponentScope, config.properties.genericTypeInstances, { config }));
|
|
106
102
|
}
|
|
107
103
|
return genericsContext;
|
|
108
104
|
}
|
|
@@ -1,30 +1,74 @@
|
|
|
1
|
+
import type * as RDF from '@rdfjs/types';
|
|
1
2
|
import type { Resource, RdfObjectLoader } from 'rdf-object';
|
|
3
|
+
import type { IParamValueConflict } from './parameterproperty/ParameterPropertyHandlerRange';
|
|
2
4
|
/**
|
|
3
5
|
* Context for binding generic types to a concrete range value.
|
|
4
6
|
*/
|
|
5
7
|
export declare class GenericsContext {
|
|
8
|
+
private static readonly XSD_INHERITANCE_TABLE;
|
|
6
9
|
private readonly objectLoader;
|
|
7
10
|
/**
|
|
8
11
|
* Set of generic type ids.
|
|
9
12
|
* @private
|
|
10
13
|
*/
|
|
11
|
-
|
|
14
|
+
genericTypeIds: Record<string, boolean>;
|
|
12
15
|
/**
|
|
13
16
|
* Mapping of generic type id to the resolved range.
|
|
14
17
|
* @private
|
|
15
18
|
*/
|
|
16
|
-
|
|
19
|
+
bindings: Record<string, Resource>;
|
|
17
20
|
constructor(objectLoader: RdfObjectLoader, genericTypeParameters: Resource[]);
|
|
18
21
|
/**
|
|
19
22
|
* Try to to bind the given value to the given generic.
|
|
20
23
|
* @param genericTypeId IRI of the generic to bind.
|
|
21
24
|
* @param value The value to bind to.
|
|
22
|
-
* @param
|
|
25
|
+
* @param valueTypeValidator Callback for validating values against types.
|
|
26
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
27
|
+
* @return boolean True if the binding was valid and took place.
|
|
23
28
|
*/
|
|
24
|
-
bindGenericTypeToValue(genericTypeId: string, value: Resource | undefined,
|
|
29
|
+
bindGenericTypeToValue(genericTypeId: string, value: Resource | undefined, valueTypeValidator: (subValue: Resource | undefined, subType: Resource) => IParamValueConflict | undefined, typeTypeValidator: (subValue: Resource, subType: Resource) => IParamValueConflict | undefined): IParamValueConflict | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Try to bind the given range to the given generic.
|
|
32
|
+
* @param genericTypeId IRI of the generic to bind.
|
|
33
|
+
* @param range The range to bind to.
|
|
34
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
35
|
+
* @return boolean True if the binding was valid and took place.
|
|
36
|
+
*/
|
|
37
|
+
bindGenericTypeToRange(genericTypeId: string, range: Resource, typeTypeValidator: (subType: Resource, superType: Resource) => IParamValueConflict | undefined): IParamValueConflict | undefined;
|
|
25
38
|
/**
|
|
26
39
|
* Infer the parameter range of the given value.
|
|
27
40
|
* @param value A value.
|
|
28
41
|
*/
|
|
29
|
-
inferValueRange(value: Resource | undefined): Resource
|
|
42
|
+
inferValueRange(value: Resource | undefined): Resource | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Merge the given ranges into a new range.
|
|
45
|
+
* This will return undefined in the ranges are incompatible.
|
|
46
|
+
*
|
|
47
|
+
* If one type is more specific than the other, it will return the narrowest type.
|
|
48
|
+
*
|
|
49
|
+
* @param rangeA A first range.
|
|
50
|
+
* @param rangeB A second range.
|
|
51
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
52
|
+
*/
|
|
53
|
+
mergeRanges(rangeA: Resource, rangeB: Resource, typeTypeValidator: (subType: Resource, superType: Resource) => IParamValueConflict | undefined): Resource | undefined;
|
|
54
|
+
protected mergeUnion(rangeUnion: Resource, rangeOther: Resource, typeValidator: (subType: Resource, superType: Resource) => IParamValueConflict | undefined): Resource | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Check if the given type is a subtype of the given super type.
|
|
57
|
+
* @param type A type node.
|
|
58
|
+
* @param potentialSuperType A potential super type node.
|
|
59
|
+
*/
|
|
60
|
+
isXsdSubType(type: RDF.Term, potentialSuperType: RDF.Term): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Apply the give generic type instances for the given component's generic type parameters.
|
|
63
|
+
*
|
|
64
|
+
* This will throw if the number of passed instances does not match with
|
|
65
|
+
* the number of generic type parameters on the component.
|
|
66
|
+
*
|
|
67
|
+
* @param component The component
|
|
68
|
+
* @param genericTypeInstances The generic type instances to apply.
|
|
69
|
+
* @param errorContext The context for error reporting.
|
|
70
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
71
|
+
* @return boolean False if the application failed due to a binding error. True otherwise
|
|
72
|
+
*/
|
|
73
|
+
bindComponentGenericTypes(component: Resource, genericTypeInstances: Resource[], errorContext: Record<string, Resource | Resource[] | string>, typeTypeValidator: (subValue: Resource, subType: Resource) => IParamValueConflict | undefined): IParamValueConflict | undefined;
|
|
30
74
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GenericsContext = void 0;
|
|
4
|
+
const ErrorResourcesContext_1 = require("../util/ErrorResourcesContext");
|
|
5
|
+
const ParameterPropertyHandlerRange_1 = require("./parameterproperty/ParameterPropertyHandlerRange");
|
|
4
6
|
/**
|
|
5
7
|
* Context for binding generic types to a concrete range value.
|
|
6
8
|
*/
|
|
@@ -12,7 +14,7 @@ class GenericsContext {
|
|
|
12
14
|
this.bindings = {};
|
|
13
15
|
for (const genericTypeParameter of genericTypeParameters) {
|
|
14
16
|
if (genericTypeParameter.property.range) {
|
|
15
|
-
this.bindings[genericTypeParameter.value] = genericTypeParameter.
|
|
17
|
+
this.bindings[genericTypeParameter.value] = genericTypeParameter.property.range;
|
|
16
18
|
}
|
|
17
19
|
}
|
|
18
20
|
}
|
|
@@ -20,27 +22,68 @@ class GenericsContext {
|
|
|
20
22
|
* Try to to bind the given value to the given generic.
|
|
21
23
|
* @param genericTypeId IRI of the generic to bind.
|
|
22
24
|
* @param value The value to bind to.
|
|
23
|
-
* @param
|
|
25
|
+
* @param valueTypeValidator Callback for validating values against types.
|
|
26
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
27
|
+
* @return boolean True if the binding was valid and took place.
|
|
24
28
|
*/
|
|
25
|
-
bindGenericTypeToValue(genericTypeId, value,
|
|
29
|
+
bindGenericTypeToValue(genericTypeId, value, valueTypeValidator, typeTypeValidator) {
|
|
26
30
|
// Fail if an unknown generic type is referenced
|
|
27
31
|
if (!(genericTypeId in this.genericTypeIds)) {
|
|
28
|
-
return
|
|
32
|
+
return {
|
|
33
|
+
description: `unknown generic <${genericTypeId}> is being referenced`,
|
|
34
|
+
context: { value },
|
|
35
|
+
};
|
|
29
36
|
}
|
|
30
37
|
// If the generic was already bound to a range, validate it
|
|
31
38
|
const existingRange = this.bindings[genericTypeId];
|
|
32
|
-
if (existingRange
|
|
33
|
-
|
|
39
|
+
if (existingRange) {
|
|
40
|
+
const subConflict = valueTypeValidator(value, existingRange);
|
|
41
|
+
if (subConflict) {
|
|
42
|
+
return {
|
|
43
|
+
description: `generic <${genericTypeId}> with existing range "${ParameterPropertyHandlerRange_1.ParameterPropertyHandlerRange.rangeToDisplayString(existingRange, this)}" can not contain the given value`,
|
|
44
|
+
context: { existingRange, value },
|
|
45
|
+
causes: [subConflict],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
34
48
|
}
|
|
35
49
|
// Infer type of value
|
|
36
50
|
const valueRange = this.inferValueRange(value);
|
|
37
|
-
if (valueRange
|
|
38
|
-
|
|
39
|
-
// TODO: this will be needed for resources with common inheritance hierarchies
|
|
40
|
-
// Save inferred type
|
|
41
|
-
this.bindings[genericTypeId] = valueRange;
|
|
51
|
+
if (!valueRange) {
|
|
52
|
+
return;
|
|
42
53
|
}
|
|
43
|
-
|
|
54
|
+
// Save inferred type
|
|
55
|
+
return this.bindGenericTypeToRange(genericTypeId, valueRange, typeTypeValidator);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Try to bind the given range to the given generic.
|
|
59
|
+
* @param genericTypeId IRI of the generic to bind.
|
|
60
|
+
* @param range The range to bind to.
|
|
61
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
62
|
+
* @return boolean True if the binding was valid and took place.
|
|
63
|
+
*/
|
|
64
|
+
bindGenericTypeToRange(genericTypeId, range, typeTypeValidator) {
|
|
65
|
+
// Fail if an unknown generic type is referenced
|
|
66
|
+
if (!(genericTypeId in this.genericTypeIds)) {
|
|
67
|
+
return {
|
|
68
|
+
description: `unknown generic <${genericTypeId}> is being referenced`,
|
|
69
|
+
context: {},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// If we already had a range, check if they match
|
|
73
|
+
if (this.bindings[genericTypeId]) {
|
|
74
|
+
const mergedRange = this.mergeRanges(this.bindings[genericTypeId], range, typeTypeValidator);
|
|
75
|
+
if (!mergedRange) {
|
|
76
|
+
return {
|
|
77
|
+
description: `generic <${genericTypeId}> with existing range "${ParameterPropertyHandlerRange_1.ParameterPropertyHandlerRange.rangeToDisplayString(this.bindings[genericTypeId], this)}" can not be bound to range "${ParameterPropertyHandlerRange_1.ParameterPropertyHandlerRange.rangeToDisplayString(range, this)}"`,
|
|
78
|
+
context: {
|
|
79
|
+
existingRange: this.bindings[genericTypeId],
|
|
80
|
+
newRange: range,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
range = mergedRange;
|
|
85
|
+
}
|
|
86
|
+
this.bindings[genericTypeId] = range;
|
|
44
87
|
}
|
|
45
88
|
/**
|
|
46
89
|
* Infer the parameter range of the given value.
|
|
@@ -49,15 +92,235 @@ class GenericsContext {
|
|
|
49
92
|
inferValueRange(value) {
|
|
50
93
|
// Value is undefined
|
|
51
94
|
if (!value) {
|
|
52
|
-
return
|
|
95
|
+
return this.objectLoader.createCompactedResource({ '@type': 'ParameterRangeUndefined' });
|
|
53
96
|
}
|
|
54
97
|
// Value is a literal
|
|
55
98
|
if (value.term.termType === 'Literal') {
|
|
56
|
-
return
|
|
99
|
+
return this.objectLoader.createCompactedResource(value.term.datatype);
|
|
57
100
|
}
|
|
58
101
|
// Value is a named node
|
|
59
|
-
|
|
102
|
+
const types = value.properties.type;
|
|
103
|
+
if (types.length > 1) {
|
|
104
|
+
return this.objectLoader.createCompactedResource({
|
|
105
|
+
'@type': 'ParameterRangeUnion',
|
|
106
|
+
parameterRangeElements: types,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return types[0];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Merge the given ranges into a new range.
|
|
113
|
+
* This will return undefined in the ranges are incompatible.
|
|
114
|
+
*
|
|
115
|
+
* If one type is more specific than the other, it will return the narrowest type.
|
|
116
|
+
*
|
|
117
|
+
* @param rangeA A first range.
|
|
118
|
+
* @param rangeB A second range.
|
|
119
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
120
|
+
*/
|
|
121
|
+
mergeRanges(rangeA, rangeB, typeTypeValidator) {
|
|
122
|
+
var _a, _b;
|
|
123
|
+
// Check if one is a subtype of the other (and return the most specific type)
|
|
124
|
+
if (!typeTypeValidator(rangeA, rangeB)) {
|
|
125
|
+
return rangeA;
|
|
126
|
+
}
|
|
127
|
+
if (!typeTypeValidator(rangeB, rangeA)) {
|
|
128
|
+
return rangeB;
|
|
129
|
+
}
|
|
130
|
+
// Check XSD inheritance relationship
|
|
131
|
+
if (this.isXsdSubType(rangeA.term, rangeB.term)) {
|
|
132
|
+
return rangeA;
|
|
133
|
+
}
|
|
134
|
+
if (this.isXsdSubType(rangeB.term, rangeA.term)) {
|
|
135
|
+
return rangeB;
|
|
136
|
+
}
|
|
137
|
+
// If a range is a wildcard, return the other type
|
|
138
|
+
if (rangeA.isA('ParameterRangeWildcard')) {
|
|
139
|
+
return rangeB;
|
|
140
|
+
}
|
|
141
|
+
if (rangeB.isA('ParameterRangeWildcard')) {
|
|
142
|
+
return rangeA;
|
|
143
|
+
}
|
|
144
|
+
// Ranges always match with generic references
|
|
145
|
+
if (rangeA.isA('ParameterRangeGenericTypeReference')) {
|
|
146
|
+
return rangeB;
|
|
147
|
+
}
|
|
148
|
+
if (rangeB.isA('ParameterRangeGenericTypeReference')) {
|
|
149
|
+
return rangeA;
|
|
150
|
+
}
|
|
151
|
+
// Check parameter range types
|
|
152
|
+
if ((_a = rangeA.property.type) === null || _a === void 0 ? void 0 : _a.term.equals((_b = rangeB.property.type) === null || _b === void 0 ? void 0 : _b.term)) {
|
|
153
|
+
// Check sub-value for specific param range cases
|
|
154
|
+
if (rangeA.isA('ParameterRangeArray') ||
|
|
155
|
+
rangeA.isA('ParameterRangeRest') ||
|
|
156
|
+
rangeA.isA('ParameterRangeKeyof')) {
|
|
157
|
+
const valueA = rangeA.property.parameterRangeValue;
|
|
158
|
+
const valueB = rangeB.property.parameterRangeValue;
|
|
159
|
+
const merged = this.mergeRanges(valueA, valueB, typeTypeValidator);
|
|
160
|
+
if (!merged) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
return this.objectLoader.createCompactedResource({
|
|
164
|
+
'@type': rangeA.property.type,
|
|
165
|
+
parameterRangeValue: merged,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Check sub-values for specific param range cases
|
|
169
|
+
if (rangeA.isA('ParameterRangeUnion') ||
|
|
170
|
+
rangeA.isA('ParameterRangeIntersection') ||
|
|
171
|
+
rangeA.isA('ParameterRangeTuple')) {
|
|
172
|
+
const valuesA = rangeA.properties.parameterRangeElements;
|
|
173
|
+
const valuesB = rangeB.properties.parameterRangeElements;
|
|
174
|
+
if (valuesA.length !== valuesB.length) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const merged = valuesA.map((valueA, i) => this.mergeRanges(valueA, valuesB[i], typeTypeValidator));
|
|
178
|
+
if (merged.some(subValue => !subValue)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
return this.objectLoader.createCompactedResource({
|
|
182
|
+
'@type': rangeA.property.type,
|
|
183
|
+
parameterRangeElements: merged,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Check sub-values for generic components
|
|
187
|
+
if (rangeA.isA('ParameterRangeGenericComponent')) {
|
|
188
|
+
const mergedComponent = this.mergeRanges(rangeA.property.component, rangeB.property.component, typeTypeValidator);
|
|
189
|
+
if (!mergedComponent) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const valuesA = rangeA.properties.genericTypeInstances;
|
|
193
|
+
const valuesB = rangeB.properties.genericTypeInstances;
|
|
194
|
+
if (valuesA.length !== valuesB.length) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const merged = valuesA.map((valueA, i) => this.mergeRanges(valueA, valuesB[i], typeTypeValidator));
|
|
198
|
+
if (merged.some(subValue => !subValue)) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
return this.objectLoader.createCompactedResource({
|
|
202
|
+
'@type': 'ParameterRangeGenericComponent',
|
|
203
|
+
component: mergedComponent,
|
|
204
|
+
genericTypeInstances: merged,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return rangeA;
|
|
208
|
+
}
|
|
209
|
+
// Handle left or right being a union
|
|
210
|
+
if (rangeA.isA('ParameterRangeUnion')) {
|
|
211
|
+
return this.mergeUnion(rangeA, rangeB, typeTypeValidator);
|
|
212
|
+
}
|
|
213
|
+
if (rangeB.isA('ParameterRangeUnion')) {
|
|
214
|
+
return this.mergeUnion(rangeB, rangeA, typeTypeValidator);
|
|
215
|
+
}
|
|
216
|
+
// Check if the range refers to a component with a generic type
|
|
217
|
+
// TODO: somehow pass the range's component and genericTypeInstances (like in ParameterPropertyHandlerRange)?
|
|
218
|
+
if (rangeA.isA('ParameterRangeGenericComponent')) {
|
|
219
|
+
return this.mergeRanges(rangeA.property.component, rangeB, typeTypeValidator);
|
|
220
|
+
}
|
|
221
|
+
if (rangeB.isA('ParameterRangeGenericComponent')) {
|
|
222
|
+
return this.mergeRanges(rangeB.property.component, rangeA, typeTypeValidator);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
mergeUnion(rangeUnion, rangeOther, typeValidator) {
|
|
226
|
+
const elements = rangeUnion.properties.parameterRangeElements;
|
|
227
|
+
const mergedValues = elements
|
|
228
|
+
.map(element => this.mergeRanges(rangeOther, element, typeValidator))
|
|
229
|
+
.filter(Boolean);
|
|
230
|
+
if (mergedValues.length === 0) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (mergedValues.length === 1) {
|
|
234
|
+
return mergedValues[0];
|
|
235
|
+
}
|
|
236
|
+
return this.objectLoader.createCompactedResource({
|
|
237
|
+
'@type': 'ParameterRangeUnion',
|
|
238
|
+
parameterRangeElements: mergedValues,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Check if the given type is a subtype of the given super type.
|
|
243
|
+
* @param type A type node.
|
|
244
|
+
* @param potentialSuperType A potential super type node.
|
|
245
|
+
*/
|
|
246
|
+
isXsdSubType(type, potentialSuperType) {
|
|
247
|
+
const values = GenericsContext.XSD_INHERITANCE_TABLE[potentialSuperType.value];
|
|
248
|
+
return values && values.has(type.value);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Apply the give generic type instances for the given component's generic type parameters.
|
|
252
|
+
*
|
|
253
|
+
* This will throw if the number of passed instances does not match with
|
|
254
|
+
* the number of generic type parameters on the component.
|
|
255
|
+
*
|
|
256
|
+
* @param component The component
|
|
257
|
+
* @param genericTypeInstances The generic type instances to apply.
|
|
258
|
+
* @param errorContext The context for error reporting.
|
|
259
|
+
* @param typeTypeValidator Callback for validating sub-types against super-types.
|
|
260
|
+
* @return boolean False if the application failed due to a binding error. True otherwise
|
|
261
|
+
*/
|
|
262
|
+
bindComponentGenericTypes(component, genericTypeInstances, errorContext, typeTypeValidator) {
|
|
263
|
+
const genericTypeParameters = component.properties.genericTypeParameters;
|
|
264
|
+
// Don't do anything if no generic type instances are passed.
|
|
265
|
+
if (genericTypeInstances.length === 0) {
|
|
266
|
+
return {
|
|
267
|
+
description: `no generic type instances are passed`,
|
|
268
|
+
context: errorContext,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
// Throw if an unexpected number of generic type instances are passed.
|
|
272
|
+
if (genericTypeParameters.length !== genericTypeInstances.length) {
|
|
273
|
+
throw new ErrorResourcesContext_1.ErrorResourcesContext(`Invalid generic type instantiation: a different amount of generic types are passed (${genericTypeInstances.length}) than are defined on the component (${genericTypeParameters.length}).`, Object.assign({ passedGenerics: genericTypeInstances, definedGenerics: genericTypeParameters, component }, errorContext));
|
|
274
|
+
}
|
|
275
|
+
// Populate with manually defined generic type bindings
|
|
276
|
+
for (const [i, genericTypeInstance] of genericTypeInstances.entries()) {
|
|
277
|
+
// Remap generic type IRI to inner generic type IRI
|
|
278
|
+
const genericTypeIdInner = genericTypeParameters[i].value;
|
|
279
|
+
if (genericTypeInstance.property.parameterRangeGenericBindings) {
|
|
280
|
+
const subConflict = this.bindGenericTypeToRange(genericTypeIdInner, genericTypeInstance.property.parameterRangeGenericBindings, typeTypeValidator);
|
|
281
|
+
if (subConflict) {
|
|
282
|
+
return {
|
|
283
|
+
description: `invalid binding for generic <${genericTypeIdInner}>`,
|
|
284
|
+
context: errorContext,
|
|
285
|
+
causes: [subConflict],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
this.genericTypeIds[genericTypeIdInner] = true;
|
|
290
|
+
}
|
|
60
291
|
}
|
|
61
292
|
}
|
|
62
293
|
exports.GenericsContext = GenericsContext;
|
|
294
|
+
GenericsContext.XSD_INHERITANCE_TABLE = {
|
|
295
|
+
'http://www.w3.org/2001/XMLSchema#number': new Set([
|
|
296
|
+
'http://www.w3.org/2001/XMLSchema#integer',
|
|
297
|
+
'http://www.w3.org/2001/XMLSchema#long',
|
|
298
|
+
'http://www.w3.org/2001/XMLSchema#int',
|
|
299
|
+
'http://www.w3.org/2001/XMLSchema#byte',
|
|
300
|
+
'http://www.w3.org/2001/XMLSchema#short',
|
|
301
|
+
'http://www.w3.org/2001/XMLSchema#negativeInteger',
|
|
302
|
+
'http://www.w3.org/2001/XMLSchema#nonNegativeInteger',
|
|
303
|
+
'http://www.w3.org/2001/XMLSchema#nonPositiveInteger',
|
|
304
|
+
'http://www.w3.org/2001/XMLSchema#positiveInteger',
|
|
305
|
+
'http://www.w3.org/2001/XMLSchema#unsignedByte',
|
|
306
|
+
'http://www.w3.org/2001/XMLSchema#unsignedInt',
|
|
307
|
+
'http://www.w3.org/2001/XMLSchema#unsignedLong',
|
|
308
|
+
'http://www.w3.org/2001/XMLSchema#unsignedShort',
|
|
309
|
+
'http://www.w3.org/2001/XMLSchema#double',
|
|
310
|
+
'http://www.w3.org/2001/XMLSchema#decimal',
|
|
311
|
+
'http://www.w3.org/2001/XMLSchema#float',
|
|
312
|
+
]),
|
|
313
|
+
'http://www.w3.org/2001/XMLSchema#string': new Set([
|
|
314
|
+
'http://www.w3.org/2001/XMLSchema#normalizedString',
|
|
315
|
+
'http://www.w3.org/2001/XMLSchema#anyURI',
|
|
316
|
+
'http://www.w3.org/2001/XMLSchema#base64Binary',
|
|
317
|
+
'http://www.w3.org/2001/XMLSchema#language',
|
|
318
|
+
'http://www.w3.org/2001/XMLSchema#Name',
|
|
319
|
+
'http://www.w3.org/2001/XMLSchema#NCName',
|
|
320
|
+
'http://www.w3.org/2001/XMLSchema#NMTOKEN',
|
|
321
|
+
'http://www.w3.org/2001/XMLSchema#token',
|
|
322
|
+
'http://www.w3.org/2001/XMLSchema#hexBinary',
|
|
323
|
+
'http://www.w3.org/2001/XMLSchema#langString',
|
|
324
|
+
]),
|
|
325
|
+
};
|
|
63
326
|
//# sourceMappingURL=GenericsContext.js.map
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { RdfObjectLoader, Resource } from 'rdf-object';
|
|
2
2
|
import type { GenericsContext } from './GenericsContext';
|
|
3
|
+
import { ParameterPropertyHandlerRange } from './parameterproperty/ParameterPropertyHandlerRange';
|
|
3
4
|
/**
|
|
4
5
|
* Handles component parameters in the context of a config.
|
|
5
6
|
*/
|
|
6
7
|
export declare class ParameterHandler {
|
|
7
8
|
private readonly objectLoader;
|
|
8
9
|
private readonly parameterPropertyHandlers;
|
|
10
|
+
readonly parameterPropertyHandlerRange: ParameterPropertyHandlerRange;
|
|
9
11
|
constructor(options: IParameterHandlerOptions);
|
|
10
12
|
/**
|
|
11
13
|
* Obtain the values of the given parameter in the context of the given config.
|
|
@@ -17,7 +17,7 @@ class ParameterHandler {
|
|
|
17
17
|
new ParameterPropertyHandlerDefaultScoped_1.ParameterPropertyHandlerDefaultScoped(this.objectLoader),
|
|
18
18
|
new ParameterPropertyHandlerDefault_1.ParameterPropertyHandlerDefault(this.objectLoader),
|
|
19
19
|
new ParameterPropertyHandlerFixed_1.ParameterPropertyHandlerFixed(this.objectLoader),
|
|
20
|
-
new ParameterPropertyHandlerRange_1.ParameterPropertyHandlerRange(this.objectLoader),
|
|
20
|
+
this.parameterPropertyHandlerRange = new ParameterPropertyHandlerRange_1.ParameterPropertyHandlerRange(this.objectLoader),
|
|
21
21
|
new ParameterPropertyHandlerLazy_1.ParameterPropertyHandlerLazy(),
|
|
22
22
|
];
|
|
23
23
|
}
|