Inline attributes semantics and tests

This commit is contained in:
barsdeveloper
2023-04-09 10:41:50 +02:00
parent 0a40f0b33c
commit 53d79a16f5
22 changed files with 508 additions and 382 deletions

View File

@@ -1,10 +1,11 @@
import ByteEntity from "../entity/ByteEntity.js"
import Configuration from "../Configuration.js"
import EnumEntity from "../entity/EnumEntity.js"
import FormatTextEntity from "../entity/FormatTextEntity.js"
import FunctionReferenceEntity from "../entity/FunctionReferenceEntity.js"
import GuidEntity from "../entity/GuidEntity.js"
import IdentifierEntity from "../entity/IdentifierEntity.js"
import IndexedArray from "../entity/IndexedArray.js"
import IEntity from "../entity/IEntity.js"
import Integer64Entity from "../entity/Integer64Entity.js"
import IntegerEntity from "../entity/IntegerEntity.js"
import InvariantTextEntity from "../entity/InvariantTextEntity.js"
@@ -273,16 +274,44 @@ export default class Grammar {
return result
}
/**
* @param {EntityConstructor} entityType
* @param {String[]} key
* @returns {AttributeInformation}
*/
static getAttribute(entityType, key) {
let result
let type
if (entityType instanceof UnionType) {
for (let t of entityType.types) {
if (result = this.getAttribute(t, key)) {
return result
}
}
}
if (entityType instanceof IEntity.constructor) {
result = entityType.attributes[key[0]]
type = result?.type
} else if (entityType instanceof Array) {
result = entityType[key[0]]
type = result
}
if (key.length > 1) {
return this.getAttribute(type, key.slice(1))
}
return result
}
static createAttributeGrammar(entityType, valueSeparator = this.equalSeparation) {
return P.seq(
this.attributeName,
valueSeparator,
).chain(([attributeName, _1]) => {
attributeName = Utility.encodeKeyName(attributeName)
const attributeKey = attributeName.split(Configuration.keysSeparator)
return this
.grammarFor(entityType.attributes[attributeName], undefined)
.grammarFor(this.getAttribute(entityType, attributeKey))
.map(attributeValue =>
values => values[attributeName] = attributeValue
values => Utility.objectSet(values, attributeKey, attributeValue, true)
)
})
}
@@ -563,7 +592,7 @@ export default class Grammar {
})
)
static indexedArrayEntry = P.lazy(() => {
static inlinedArrayEntry = P.lazy(() => {
return P.seq(
this.symbol,
this.regexMap(
@@ -574,8 +603,7 @@ export default class Grammar {
.chain(([symbol, _1]) =>
this.grammarFor(ObjectEntity.attributes[symbol])
.map(currentValue =>
values => (values[symbol] ??= new IndexedArray(currentValue.constructor))
.value.push(currentValue)
values => (values[symbol] ??= []).push(currentValue)
)
)
})
@@ -588,7 +616,7 @@ export default class Grammar {
P.alt(
this.customProperty,
this.createAttributeGrammar(ObjectEntity),
this.indexedArrayEntry
this.inlinedArrayEntry
)
)
.map(([_0, entry]) => entry)

View File

@@ -1,5 +1,4 @@
import Grammar from "./Grammar.js"
import IndexedArray from "../entity/IndexedArray.js"
import SerializerFactory from "./SerializerFactory.js"
import Utility from "../Utility.js"
@@ -14,13 +13,13 @@ export default class Serializer {
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
static bracketsWrapped = ((v, entityType) => `(${v})`)
/** @type {(v: String, entityType: AnyValueConstructor) => String} */
static notWrapped = ((v, entityType) => v)
/** @type {(v: String) => String} */
static same = (v => v)
/** @param {AnyValueConstructor} entityType */
constructor(
entityType,
wrap = Serializer.bracketsWrapped,
wrap = Serializer.same,
attributePrefix = "",
attributeSeparator = ",",
trailingSeparator = false,
@@ -85,40 +84,34 @@ export default class Serializer {
Object.keys(attributes),
Object.keys(entity)
)
let first = true
for (const key of keys) {
const value = entity[key]
if (value !== undefined && this.showProperty(entity, key)) {
const isSerialized = Utility.isSerialized(entity, key)
result += (result.length ? attributeSeparator : "")
if (first) {
first = false
} else {
result += attributeSeparator
}
if (attributes[key]?.inlined) {
result += this.doWrite(
value,
insideString,
Serializer.notWrapped,
`${attributePrefix}${key}.`,
attributeSeparator,
trailingSeparator,
attributeValueConjunctionSign,
attributeKeyPrinter
)
continue
}
if (value instanceof IndexedArray) {
result += this.doWrite(
value,
insideString,
wrap,
Serializer.same,
attributePrefix,
attributeSeparator,
trailingSeparator,
false,
attributeValueConjunctionSign,
index => `(${index})`
attributes[key].type instanceof Array
? k => attributeKeyPrinter(`${key}(${k})`)
: k => attributeKeyPrinter(`${key}.${k}`),
)
continue
}
result +=
attributePrefix
+ Utility.decodeKeyName(this.attributeKeyPrinter(key))
+ attributeKeyPrinter(key)
+ this.attributeValueConjunctionSign
+ (
isSerialized
@@ -127,7 +120,7 @@ export default class Serializer {
)
}
}
if (this.trailingSeparator && result.length) {
if (trailingSeparator && result.length) {
// append separator at the end if asked and there was printed content
result += this.attributeSeparator
}

View File

@@ -28,7 +28,7 @@ export default class SerializerFactory {
/**
* @template {AnyValue} T
* @param {new () => T} entity
* @param {new (...any) => T} entity
* @returns {Serializer<T>}
*/
static getSerializer(entity) {