@itwin/ecschema-metadata 5.15.0-dev.9 → 5.16.0-dev.2
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 +11 -1
- package/lib/cjs/SchemaView/SchemaView.d.ts +33 -15
- package/lib/cjs/SchemaView/SchemaView.d.ts.map +1 -1
- package/lib/cjs/SchemaView/SchemaView.js +97 -34
- package/lib/cjs/SchemaView/SchemaView.js.map +1 -1
- package/lib/cjs/SchemaView/SchemaViewBinaryReader.js +1 -0
- package/lib/cjs/SchemaView/SchemaViewBinaryReader.js.map +1 -1
- package/lib/cjs/SchemaView/SchemaViewInterfaces.d.ts +12 -0
- package/lib/cjs/SchemaView/SchemaViewInterfaces.d.ts.map +1 -1
- package/lib/cjs/SchemaView/SchemaViewInterfaces.js.map +1 -1
- package/lib/esm/SchemaView/SchemaView.d.ts +33 -15
- package/lib/esm/SchemaView/SchemaView.d.ts.map +1 -1
- package/lib/esm/SchemaView/SchemaView.js +97 -34
- package/lib/esm/SchemaView/SchemaView.js.map +1 -1
- package/lib/esm/SchemaView/SchemaViewBinaryReader.js +1 -0
- package/lib/esm/SchemaView/SchemaViewBinaryReader.js.map +1 -1
- package/lib/esm/SchemaView/SchemaViewInterfaces.d.ts +12 -0
- package/lib/esm/SchemaView/SchemaViewInterfaces.d.ts.map +1 -1
- package/lib/esm/SchemaView/SchemaViewInterfaces.js.map +1 -1
- package/package.json +7 -7
|
@@ -137,8 +137,8 @@ export class SchemaView {
|
|
|
137
137
|
throw new Error("SchemaView is not mergeable: create it via SchemaView.createMergeable to merge fragments.");
|
|
138
138
|
this._mergeContext.mergeBlob(blob);
|
|
139
139
|
// A new fragment can add subclasses to an already-present base class, so the derived-class map
|
|
140
|
-
// must be rebuilt. transitiveBaseCache
|
|
141
|
-
// before it (dependency order), so an append never adds an ancestor to an already-cached class.
|
|
140
|
+
// must be rebuilt. transitiveBaseCache and PropertyRef.overriddenProperty stay valid: a class's ancestors
|
|
141
|
+
// are always merged before it (dependency order), so an append never adds an ancestor to an already-cached class.
|
|
142
142
|
this[_storage].derivedClassMap = undefined;
|
|
143
143
|
}
|
|
144
144
|
// --- Internal helpers used by view objects ---
|
|
@@ -228,12 +228,18 @@ export class SchemaView {
|
|
|
228
228
|
// 1. Base class (recursive, depth-first)
|
|
229
229
|
if (cls.baseClassIdx !== -1)
|
|
230
230
|
this._collectProperties(cls.baseClassIdx, merged);
|
|
231
|
-
// 2. Mixins in declaration order
|
|
231
|
+
// 2. Mixins in declaration order. Each mixin is resolved on its own so its overrides win over its
|
|
232
|
+
// ancestors, then only adds names not already provided by the base class or an earlier mixin.
|
|
232
233
|
for (let i = 0; i < cls.mixinCount; i++) {
|
|
233
234
|
const mixinIdx = this[_storage].classMixins[cls.mixinStartIdx + i];
|
|
234
235
|
if (mixinIdx === -1 || mixinIdx === undefined)
|
|
235
236
|
continue; // safety: dangling mixin ref
|
|
236
|
-
|
|
237
|
+
const mixinProperties = new Map();
|
|
238
|
+
this._collectProperties(mixinIdx, mixinProperties);
|
|
239
|
+
for (const [nameKey, resolved] of mixinProperties) {
|
|
240
|
+
if (!merged.has(nameKey))
|
|
241
|
+
merged.set(nameKey, resolved);
|
|
242
|
+
}
|
|
237
243
|
}
|
|
238
244
|
// 3. Own properties - always override
|
|
239
245
|
for (let i = 0; i < cls.ownPropCount; i++) {
|
|
@@ -242,27 +248,62 @@ export class SchemaView {
|
|
|
242
248
|
merged.set(nameKey, { ref, classIdx });
|
|
243
249
|
}
|
|
244
250
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
/** Finds the property declaration that a property of the given class overrides.
|
|
252
|
+
* Searches the base class and its ancestors first, then each mixin in declaration order.
|
|
253
|
+
*/
|
|
254
|
+
_findOverriddenProperty(classIdx, nameKey) {
|
|
255
|
+
const cls = this[_storage].classes[classIdx];
|
|
256
|
+
if (cls === undefined || cls.type === ClassType.View)
|
|
257
|
+
return undefined;
|
|
258
|
+
if (cls.baseClassIdx !== -1) {
|
|
259
|
+
const found = this._findPropertyDeclaration(cls.baseClassIdx, nameKey);
|
|
260
|
+
if (found !== undefined)
|
|
261
|
+
return found;
|
|
262
|
+
}
|
|
263
|
+
for (let i = 0; i < cls.mixinCount; i++) {
|
|
264
|
+
const mixinIdx = this[_storage].classMixins[cls.mixinStartIdx + i];
|
|
265
|
+
if (mixinIdx === -1 || mixinIdx === undefined)
|
|
256
266
|
continue; // safety: dangling mixin ref
|
|
257
|
-
this.
|
|
267
|
+
const found = this._findPropertyDeclaration(mixinIdx, nameKey);
|
|
268
|
+
if (found !== undefined)
|
|
269
|
+
return found;
|
|
270
|
+
}
|
|
271
|
+
return undefined;
|
|
272
|
+
}
|
|
273
|
+
_findPropertyDeclaration(classIdx, nameKey) {
|
|
274
|
+
const cls = this[_storage].classes[classIdx];
|
|
275
|
+
if (cls === undefined)
|
|
276
|
+
return undefined; // safety: dangling index from excluded schema
|
|
277
|
+
for (let i = 0; i < cls.ownPropCount; i++) {
|
|
278
|
+
const ref = this[_storage].propertyRefs[cls.ownPropStart + i];
|
|
279
|
+
if (this[_storage].lowerStrings[this[_storage].propDefs[ref.defIdx].nameStringIdx] === nameKey)
|
|
280
|
+
return { ref, classIdx };
|
|
258
281
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
282
|
+
return this._findOverriddenProperty(classIdx, nameKey);
|
|
283
|
+
}
|
|
284
|
+
/** Returns the first declaration matching `predicate`, starting with the given declaration and
|
|
285
|
+
* continuing with the declarations it overrides.
|
|
286
|
+
* @internal
|
|
287
|
+
*/
|
|
288
|
+
findPropertyDefInOverrides(ref, classIdx, predicate) {
|
|
289
|
+
let current = { ref, classIdx };
|
|
290
|
+
while (current !== null) {
|
|
291
|
+
const def = this[_storage].propDefs[current.ref.defIdx];
|
|
292
|
+
if (predicate(def))
|
|
293
|
+
return def;
|
|
294
|
+
current = this._getOverriddenProperty(current.ref, current.classIdx);
|
|
295
|
+
}
|
|
296
|
+
return undefined;
|
|
297
|
+
}
|
|
298
|
+
/** Returns the declaration the given one overrides, resolving and storing it on the ref on first access.
|
|
299
|
+
* Caching per ref is sound because a ref belongs to exactly one class; view properties (classIdx -1) never override.
|
|
300
|
+
*/
|
|
301
|
+
_getOverriddenProperty(ref, classIdx) {
|
|
302
|
+
if (ref.overriddenProperty === undefined) {
|
|
262
303
|
const nameKey = this[_storage].lowerStrings[this[_storage].propDefs[ref.defIdx].nameStringIdx];
|
|
263
|
-
|
|
264
|
-
merged.set(nameKey, { ref, classIdx: mixinIdx });
|
|
304
|
+
ref.overriddenProperty = classIdx !== -1 ? this._findOverriddenProperty(classIdx, nameKey) ?? null : null;
|
|
265
305
|
}
|
|
306
|
+
return ref.overriddenProperty;
|
|
266
307
|
}
|
|
267
308
|
/** @internal */
|
|
268
309
|
buildDerivedClassMap() {
|
|
@@ -287,6 +328,9 @@ export class SchemaView {
|
|
|
287
328
|
// =====================================================================================
|
|
288
329
|
// SchemaView namespace - flyweight view types
|
|
289
330
|
// =====================================================================================
|
|
331
|
+
function hasCategory(def) { return def.categoryIdx !== -1; }
|
|
332
|
+
function hasKindOfQuantity(def) { return def.koqIdx !== -1; }
|
|
333
|
+
function isHiddenDef(def) { return def.isHidden; }
|
|
290
334
|
/** @beta */
|
|
291
335
|
(function (SchemaView) {
|
|
292
336
|
/** Lightweight view over a schema in a `SchemaView`. Holds only a view reference and
|
|
@@ -630,10 +674,21 @@ export class SchemaView {
|
|
|
630
674
|
}
|
|
631
675
|
get kind() { return this._def.kind; }
|
|
632
676
|
get isReadOnly() { return this._def.isReadOnly; }
|
|
633
|
-
/** Reflects the `HiddenProperty` custom attribute from `CoreCustomAttributes
|
|
634
|
-
* Properties marked hidden are typically excluded from UI display but remain
|
|
677
|
+
/** Reflects the `HiddenProperty` custom attribute from `CoreCustomAttributes` on this declaration only;
|
|
678
|
+
* see `isEffectivelyHidden`. Properties marked hidden are typically excluded from UI display but remain
|
|
679
|
+
* accessible programmatically. */
|
|
635
680
|
get isHidden() { return this._def.isHidden; }
|
|
636
|
-
/**
|
|
681
|
+
/** True if this declaration is hidden. If it is not and the property is an override, we take this from the
|
|
682
|
+
* overridden property. Limitation: `HiddenProperty(Show=true)` reads the same as no `HiddenProperty`, so it does not
|
|
683
|
+
* unhide a property whose overridden property is hidden. */
|
|
684
|
+
get isEffectivelyHidden() {
|
|
685
|
+
if (this._def.isHidden)
|
|
686
|
+
return true;
|
|
687
|
+
return this._ctx.findPropertyDefInOverrides(this._ref, this._classIdx, isHiddenDef) !== undefined;
|
|
688
|
+
}
|
|
689
|
+
/** Display priority. Higher values should be displayed more prominently. 0 means default.
|
|
690
|
+
* Not inherited from the overridden property: an omitted priority is stored as 0, which cannot be told
|
|
691
|
+
* apart from an explicit 0 that overrides a base priority. */
|
|
637
692
|
get priority() { return this._ref.priority; }
|
|
638
693
|
/** The class that declared or contributed this property through inheritance.
|
|
639
694
|
* For own properties, returns the class itself. For inherited properties, returns the
|
|
@@ -644,11 +699,21 @@ export class SchemaView {
|
|
|
644
699
|
get declaringClass() {
|
|
645
700
|
return this._classIdx !== -1 ? createClass(this._ctx, this._classIdx) : undefined;
|
|
646
701
|
}
|
|
647
|
-
/** Property category
|
|
702
|
+
/** Property category. If there is no local category and the property is an override, we take this from
|
|
703
|
+
* the overridden property. Available on all property kinds. */
|
|
648
704
|
get category() {
|
|
649
|
-
|
|
705
|
+
let idx = this._def.categoryIdx;
|
|
706
|
+
if (idx === -1 && this._ctx[_storage].propCategories.length !== 0)
|
|
707
|
+
idx = this._ctx.findPropertyDefInOverrides(this._ref, this._classIdx, hasCategory)?.categoryIdx ?? -1;
|
|
650
708
|
return idx !== -1 ? new PropertyCategory(this._ctx, idx) : undefined;
|
|
651
709
|
}
|
|
710
|
+
/** @internal */
|
|
711
|
+
get _kindOfQuantity() {
|
|
712
|
+
let idx = this._def.koqIdx;
|
|
713
|
+
if (idx === -1 && this._ctx[_storage].koqs.length !== 0)
|
|
714
|
+
idx = this._ctx.findPropertyDefInOverrides(this._ref, this._classIdx, hasKindOfQuantity)?.koqIdx ?? -1;
|
|
715
|
+
return idx !== -1 ? new KindOfQuantity(this._ctx, idx) : undefined;
|
|
716
|
+
}
|
|
652
717
|
// Type guards - real type predicates that narrow `this`
|
|
653
718
|
/** True for `SchemaView.PrimitiveProperty` and `SchemaView.PrimitiveArrayProperty`.
|
|
654
719
|
* Matches ecschema-metadata behavior where `isPrimitive()` includes primitive arrays. */
|
|
@@ -710,10 +775,9 @@ export class SchemaView {
|
|
|
710
775
|
const idx = this._def.enumIdx;
|
|
711
776
|
return idx !== -1 ? new Enumeration(this._ctx, idx) : undefined;
|
|
712
777
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
}
|
|
778
|
+
/** KindOfQuantity. If there is no local KindOfQuantity and the property is an override, we take this
|
|
779
|
+
* from the overridden property. */
|
|
780
|
+
get kindOfQuantity() { return this._kindOfQuantity; }
|
|
717
781
|
}
|
|
718
782
|
SchemaView.PrimitiveProperty = PrimitiveProperty;
|
|
719
783
|
/** An array of primitive values. Same primitive/enum fields as `PrimitiveProperty`,
|
|
@@ -730,10 +794,9 @@ export class SchemaView {
|
|
|
730
794
|
const idx = this._def.enumIdx;
|
|
731
795
|
return idx !== -1 ? new Enumeration(this._ctx, idx) : undefined;
|
|
732
796
|
}
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
}
|
|
797
|
+
/** KindOfQuantity. If there is no local KindOfQuantity and the property is an override, we take this
|
|
798
|
+
* from the overridden property. */
|
|
799
|
+
get kindOfQuantity() { return this._kindOfQuantity; }
|
|
737
800
|
get arrayMinOccurs() { return this._def.arrayMinOccurs; }
|
|
738
801
|
get arrayMaxOccurs() { return this._def.arrayMaxOccurs; }
|
|
739
802
|
}
|