This commit is contained in:
barsdeveloper
2024-05-31 15:09:48 +02:00
parent 1c2778fbf8
commit ecc71b76d1
45 changed files with 1191 additions and 1078 deletions

1145
dist/ueblueprint.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -7,13 +7,20 @@ export default class AlternativesEntity extends IEntity {
/** @type {(typeof IEntity)[]} */
static alternatives = []
static className() {
let result = super.className()
if (this.alternatives.length) {
result += " (accepting: " + this.alternatives.map(v => v.className()).join(", ") + ")"
}
return result
}
static createGrammar() {
return this.alternatives
.map(entity => entity.grammar)
.reduce((acc, cur) => !cur || cur === Grammar.unknownValue || acc === Grammar.unknownValue
? Grammar.unknownValue
: P.alt(acc, cur)
)
const grammars = this.alternatives.map(entity => entity.grammar)
if (grammars.includes(Grammar.unknownValue)) {
return Grammar.unknownValue
}
return P.alt(...grammars)
}
/**

View File

@@ -7,21 +7,30 @@ export default class ArrayEntity extends IEntity {
/** @type {typeof IEntity} */
static type
static grammar = this.createGrammar()
/** @param {InstanceType<T>[]} values */
/** @param {ExtractType<T>[]} values */
constructor(values = []) {
super()
this.values = values
}
static createGrammar(elementGrammar = this.type.grammar) {
static createGrammar(elementGrammar = this.type?.grammar ?? P.lazy(() => Grammar.unknownValue)) {
return this.inlined
? elementGrammar
: P.seq(
P.reg(/\(\s*/),
elementGrammar.sepBy(Grammar.commaSeparation).opt(),
P.reg(/\s*(?:,\s*)?\)/),
).map(([_0, values, _3]) => new this(values instanceof Array ? values : []))
P.reg(/\s*(,\s*)?\)/, 1),
).map(([_0, values, trailing]) => {
let self = this
const hasTrailing = trailing !== undefined
if (hasTrailing !== self.trailing) {
self = self.flagTrailing(hasTrailing)
}
values = values instanceof Array ? values : []
return new self(values)
}).label(`ArrayEntity of ${this.type?.className() ?? "unknown values"}`)
}
/**
@@ -29,8 +38,10 @@ export default class ArrayEntity extends IEntity {
* @param {NonNullable<T>} type
*/
static of(type) {
const result = /** @type {(typeof ArrayEntity<T>) & { type: T }} */(this.asUniqueClass())
result.type = type
const result = /** @type {typeof ArrayEntity<T> & { type: ExtractType<T>, grammar: P<ArrayEntity<T>> }} */(
this.asUniqueClass()
)
result.type = /** @type {ExtractType<T>} */(type)
this.grammar = result.createGrammar()
return result
}

View File

@@ -56,18 +56,18 @@ export default class BlueprintEntity extends ObjectEntity {
/** @param {ObjectEntity} entity */
mergeWith(entity) {
if (!entity.ScriptVariables || entity.ScriptVariables.length === 0) {
if (!entity.ScriptVariables || entity.ScriptVariables.values.length === 0) {
return this
}
if (!this.ScriptVariables || this.ScriptVariables.length === 0) {
if (!this.ScriptVariables || this.ScriptVariables.values.length === 0) {
this.ScriptVariables = entity.ScriptVariables
}
let scriptVariables = Utility.mergeArrays(
this.ScriptVariables,
entity.ScriptVariables,
this.ScriptVariables.values,
entity.ScriptVariables.values,
(l, r) => l.OriginalChangeId.value == r.OriginalChangeId.value
)
if (scriptVariables.length === this.ScriptVariables.length) {
if (scriptVariables.length === this.ScriptVariables.values.length) {
return this
}
const entries = scriptVariables.concat(scriptVariables).map((v, i) => {

View File

@@ -3,7 +3,9 @@ import IEntity from "./IEntity.js"
export default class BooleanEntity extends IEntity {
static grammar = P.regArray(/(true)|false/i).map(v => v[1] ? new this(true) : new this(false))
static grammar = P.regArray(/(true)|false/i)
.map(v => v[1] ? new this(true) : new this(false))
.label("BooleanEntity")
constructor(value = false) {
super()
@@ -14,7 +16,13 @@ export default class BooleanEntity extends IEntity {
return this.value
}
toString() {
return this.value.toString()
toString(insideString = false) {
return this.value
? insideString
? "true"
: "True"
: insideString
? "false"
: "False"
}
}

View File

@@ -1,15 +1,15 @@
import P from "parsernostrum"
import IEntity from "./IEntity.js"
import IPrintableEntity from "./IPrintableEntity.js"
import InvariantTextEntity from "./InvariantTextEntity.js"
import LocalizedTextEntity from "./LocalizedTextEntity.js"
import StringEntity from "./StringEntity.js"
export default class FormatTextEntity extends IEntity {
export default class FormatTextEntity extends IPrintableEntity {
static lookbehind = ["LOCGEN_FORMAT_NAMED", "LOCGEN_FORMAT_ORDERED"]
static grammar = P.seq(
// Resulting regex: /(LOCGEN_FORMAT_NAMED|LOCGEN_FORMAT_ORDERED)\s*/
P.reg(new RegExp(String.raw`(${this.lookbehind.reduce((acc, cur) => acc + "|" + cur)})\s*\(\s*)`), 1),
P.reg(new RegExp(String.raw`(${this.lookbehind.reduce((acc, cur) => acc + "|" + cur)})\s*`), 1),
P.alt(
...[StringEntity, LocalizedTextEntity, InvariantTextEntity, FormatTextEntity].map(type => type.grammar)
).sepBy(P.reg(/\s*\,\s*/)),
@@ -20,6 +20,7 @@ export default class FormatTextEntity extends IEntity {
result.lookbehind = lookbehind
return result
})
.label("FormatTextEntity")
/** @param {(StringEntity | LocalizedTextEntity | InvariantTextEntity | FormatTextEntity)[]} values */
constructor(values) {
@@ -27,20 +28,21 @@ export default class FormatTextEntity extends IEntity {
this.values = values
}
toString() {
print() {
const pattern = this.values?.[0]?.toString() // The pattern is always the first element of the array
if (!pattern) {
return ""
}
const values = this.values.slice(1).map(v => v.toString())
return this.lookbehind == "LOCGEN_FORMAT_NAMED"
let result = this.Self().lookbehind == "LOCGEN_FORMAT_NAMED"
? pattern.replaceAll(/\{([a-zA-Z]\w*)\}/g, (substring, arg) => {
const argLocation = values.indexOf(arg) + 1
return argLocation > 0 && argLocation < values.length
? values[argLocation]
: substring
})
: this.lookbehind == "LOCGEN_FORMAT_ORDERED"
: this.Self().lookbehind == "LOCGEN_FORMAT_ORDERED"
? pattern.replaceAll(/\{(\d+)\}/g, (substring, arg) => {
const argValue = Number(arg)
return argValue < values.length
@@ -48,5 +50,6 @@ export default class FormatTextEntity extends IEntity {
: substring
})
: ""
result = this.Self().lookbehind + "(" + result + ")"
}
}

View File

@@ -16,8 +16,8 @@ export default class FunctionReferenceEntity extends IEntity {
constructor(values) {
super(values)
/** @type {ObjectReferenceEntity} */ this.MemberParent
/** @type {String} */ this.MemberName
/** @type {GuidEntity} */ this.MemberGuid
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberParent>} */ this.MemberParent
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberName>} */ this.MemberName
/** @type {InstanceType<typeof FunctionReferenceEntity.attributes.MemberGuid>} */ this.MemberGuid
}
}

View File

@@ -10,7 +10,7 @@ if (typeof window === "undefined") {
export default class GuidEntity extends IEntity {
static grammar = P.reg(/[0-9a-fA-F]{32}/).map(v => new this(v))
static grammar = P.reg(/[0-9A-F]{32}/i).map(v => new this(v)).label("GuidEntity")
static generateGuid() {
let values = new Uint32Array(4)

View File

@@ -10,45 +10,22 @@ export default class IEntity {
/** @type {(entity: Attribute, serialized: String) => String} */
static notWrapped = (entity, serialized) => serialized
/** @type {(entity: Attribute, serialized: String) => String} */
static bracketsWrapped = (entity, serialized) => `(${serialized})`
/** @type {(entity: IEntity, serialized: String) => String} */
static defaultWrapped = (entity, serialized) => `${entity.lookbehind}(${serialized})`
static wrap = this.notWrapped
static wrap = this.defaultWrapped
static attributeSeparator = ","
static trailingSeparator = false
/** @type {(k: String) => String} */
static printKey = k => k
/** @type {P<Parser>} */
static grammar = P.failure()
/** @type {P<InstanceType<typeof this>>} */
static grammar = /** @type {any} */(P.failure())
/** @type {{ [key: String]: typeof IEntity }} */
static attributes = {}
/** @type {String | String[]} */
static lookbehind = ""
/** @type {typeof IEntity.lookbehind} */
#lookbehind = this.Self().lookbehind
get lookbehind() {
return this.#lookbehind
}
set lookbehind(value) {
throw this.#lookbehind = value
}
/** @type {String[]} */
#keys
get keys() {
return this.#keys ?? Object.keys(this.Self().attributes)
}
set keys(value) {
this.#keys = [... new Set(value)]
}
/** @type {(type: typeof IEntity) => InstanceType<typeof IEntity>} */
static default
static nullable = false
@@ -58,10 +35,30 @@ export default class IEntity {
static inlined = false // The key is a subobject or array and printed as inlined (A.B=123, A(0)=123)
static quoted = false // Key is serialized with quotes
static silent = false // Do not serialize if default
static uninitialized = false // Do not initialize with default
static trailing = false // Add attribute separator after the last attribute when serializing
/** @type {String | String[]} */
static lookbehind = ""
#lookbehind = /** @type {String} */(this.Self().lookbehind)
get lookbehind() {
return this.#lookbehind
}
set lookbehind(value) {
this.#lookbehind = value
}
/** @type {String[]} */
#keys
get keys() {
return this.#keys ?? Object.keys(this)
}
set keys(value) {
this.#keys = [... new Set(value)]
}
constructor(values = {}) {
const keys = Utility.mergeArrays(Object.keys(values.attributes), Object.keys(this.Self().attributes))
const keys = Utility.mergeArrays(Object.keys(values), Object.keys(this.Self().attributes))
for (const key of keys) {
if (values[key] !== undefined) {
this[key] = values[key]
@@ -75,6 +72,14 @@ export default class IEntity {
}
}
static className() {
let self = this
while (!self.name) {
self = Object.getPrototypeOf(self)
}
return self.name
}
/** @param {String} key */
showProperty(key) {
/** @type {IEntity} */
@@ -104,6 +109,17 @@ export default class IEntity {
return this
}
/**
* @template {typeof IEntity} T
* @this {T}
* @param {String} value
*/
static withLookbehind(value) {
const result = this.asUniqueClass()
result.lookbehind = value
return result
}
/**
* @template {typeof IEntity} T
* @this {T}
@@ -144,6 +160,16 @@ export default class IEntity {
return result
}
/**
* @template {typeof IEntity} T
* @this {T}
*/
static flagQuoted(value = true) {
const result = this.asUniqueClass()
result.quoted = value
return result
}
/**
* @template {typeof IEntity} T
* @this {T}
@@ -154,6 +180,16 @@ export default class IEntity {
return result
}
/**
* @template {typeof IEntity} T
* @this {T}
*/
static flagTrailing(value = true) {
const result = this.asUniqueClass()
result.trailing = value
return result
}
/**
* @template {typeof IEntity} T
* @this {InstanceType<T>}
@@ -206,6 +242,9 @@ export default class IEntity {
if (thisKeys.length != otherKeys.length) {
return false
}
if (this.valueOf && other.valueOf) {
return this.valueOf() === other.valueOf()
}
for (let i = 0; i < thisKeys.length; ++i) {
if (!(this[thisKeys[i]] instanceof IEntity && this[thisKeys[i]].equals(other[otherKeys[i]]))) {
return false
@@ -250,7 +289,7 @@ export default class IEntity {
}
result += serialization
}
if (Self.trailingSeparator && result.length) {
if (Self.trailing && result.length) {
result += Self.attributeSeparator
}
return Self.wrap(this, result)

View File

@@ -0,0 +1,8 @@
import IEntity from "./IEntity.js"
export default class IPrintableEntity extends IEntity {
print() {
return this.toString()
}
}

View File

@@ -1,7 +1,6 @@
import P from "parsernostrum"
import NumberEntity from "./NumberEntity.js"
// @ts-expect-error
export default class IntegerEntity extends NumberEntity {
static grammar = P.numberInteger.map(v => new this(v))

View File

@@ -1,25 +1,39 @@
import P from "parsernostrum"
import IEntity from "./IEntity.js"
import Parsernostrum from "parsernostrum"
import IPrintableEntity from "./IPrintableEntity.js"
export default class InvariantTextEntity extends IEntity {
export default class InvariantTextEntity extends IPrintableEntity {
static lookbehind = "INVTEXT"
static grammar = P.alt(
P.seq(
P.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),
P.doubleQuotedString,
P.reg(/\s*\)/)
).map(([_0, value, _2]) => new this(value)),
P.reg(new RegExp(this.lookbehind)).map(() => new this()) // InvariantTextEntity can not have arguments
).map(value => new this(value))
static grammar = Parsernostrum.alt(
Parsernostrum.seq(
Parsernostrum.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),
Parsernostrum.doubleQuotedString,
Parsernostrum.reg(/\s*\)/)
).map(([_0, value, _2]) => Number(value)),
Parsernostrum.reg(new RegExp(this.lookbehind)).map(() => 0) // InvariantTextEntity can not have arguments
)
.map(value => new this(value))
.label("InvariantTextEntity")
constructor(value = "") {
super()
this.value = value
}
toString() {
print() {
let xxxx = Parsernostrum.alt(
Parsernostrum.seq(
Parsernostrum.reg(new RegExp(`${this.lookbehind}\\s*\\(`)),
Parsernostrum.doubleQuotedString,
Parsernostrum.reg(/\s*\)/)
).map(([_0, value, _2]) => Number(value)),
Parsernostrum.reg(new RegExp(this.lookbehind)).map(() => 0) // InvariantTextEntity can not have arguments
)
return this.value
}
toString() {
return this.lookbehind + "(" + this.value + ")"
}
}

View File

@@ -27,11 +27,11 @@ export default class KeyBindingEntity extends IEntity {
constructor() {
super()
/** @type {String} */ this.ActionName
/** @type {Boolean} */ this.bShift
/** @type {Boolean} */ this.bCtrl
/** @type {Boolean} */ this.bAlt
/** @type {Boolean} */ this.bCmd
/** @type {IdentifierEntity} */ this.Key
/** @type {InstanceType<typeof KeyBindingEntity.attributes.ActionName>} */ this.ActionName
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bShift>} */ this.bShift
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bCtrl>} */ this.bCtrl
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bAlt>} */ this.bAlt
/** @type {InstanceType<typeof KeyBindingEntity.attributes.bCmd>} */ this.bCmd
/** @type {InstanceType<typeof KeyBindingEntity.attributes.Key>} */ this.Key
}
}

View File

@@ -14,7 +14,7 @@ export default class LinearColorEntity extends IEntity {
B: ColorChannelEntity.withDefault(),
A: ColorChannelEntity.withDefault(type => new type(1)),
}
static grammar = Grammar.createEntityGrammar(this, false)
static grammar = Grammar.createEntityGrammar(this).label("LinearColorEntity")
#H = new ColorChannelEntity()
get H() {
@@ -26,18 +26,35 @@ export default class LinearColorEntity extends IEntity {
#S = new ColorChannelEntity()
get S() {
return this.#H
return this.#S
}
set S(value) {
this.#H = value
this.#S = value
}
#V = new ColorChannelEntity()
get V() {
return this.#H
return this.#V
}
set V(value) {
this.#H = value
this.#V = value
}
constructor(values) {
super(values)
if (values instanceof Array) {
values = {
R: values[0] ?? 0,
G: values[1] ?? 0,
B: values[2] ?? 0,
A: values[3] ?? 1,
}
}
/** @type {InstanceType<typeof LinearColorEntity.attributes.R>} */ this.R
/** @type {InstanceType<typeof LinearColorEntity.attributes.G>} */ this.G
/** @type {InstanceType<typeof LinearColorEntity.attributes.B>} */ this.B
/** @type {InstanceType<typeof LinearColorEntity.attributes.A>} */ this.A
this.#updateHSV()
}
/** @param {Number} x */
@@ -129,23 +146,6 @@ export default class LinearColorEntity extends IEntity {
)
}
constructor(values) {
super(values)
if (values instanceof Array) {
values = {
R: values[0] ?? 0,
G: values[1] ?? 0,
B: values[2] ?? 0,
A: values[3] ?? 1,
}
}
/** @type {ColorChannelEntity} */ this.R
/** @type {ColorChannelEntity} */ this.G
/** @type {ColorChannelEntity} */ this.B
/** @type {ColorChannelEntity} */ this.A
this.#updateHSV()
}
#updateHSV() {
const r = this.R.value
const g = this.G.value
@@ -311,8 +311,4 @@ export default class LinearColorEntity extends IEntity {
toArray() {
return [this.R.value, this.G.value, this.B.value, this.A.value]
}
toString() {
return Utility.printLinearColor(this)
}
}

View File

@@ -1,24 +1,27 @@
import P from "parsernostrum"
import Utility from "../Utility.js"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
import IPrintableEntity from "./IPrintableEntity.js"
export default class LocalizedTextEntity extends IEntity {
export default class LocalizedTextEntity extends IPrintableEntity {
static lookbehind = "NSLOCTEXT"
static grammar = P.regArray(new RegExp(
String.raw`${this.attributes.lookbehind.default}\s*\(`
String.raw`${this.lookbehind}\s*\(`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*,`
+ String.raw`\s*"(${Grammar.Regex.InsideString.source})"\s*`
+ String.raw`(?:,\s+)?`
+ String.raw`(,\s+)?`
+ String.raw`\)`,
"m"
)).map(matchResult => new this(
Utility.unescapeString(matchResult[1]),
Utility.unescapeString(matchResult[2]),
Utility.unescapeString(matchResult[3]),
))
)).map(matchResult => {
const self = matchResult[4] ? this.flagTrailing() : this
return new self(
Utility.unescapeString(matchResult[1]),
Utility.unescapeString(matchResult[2]),
Utility.unescapeString(matchResult[3]),
)
}).label("LocalizedTextEntity")
#namespace
get namespace() {
@@ -44,7 +47,6 @@ export default class LocalizedTextEntity extends IEntity {
this.#value = value
}
constructor(namespace = "", key = "", value = "") {
super()
this.namespace = namespace
@@ -52,7 +54,12 @@ export default class LocalizedTextEntity extends IEntity {
this.value = value
}
toString() {
print() {
return Utility.capitalFirstLetter(this.value)
}
toString() {
const trailer = this.Self().trailing ? ", " : ""
return `${this.lookbehind}(${this.namespace}, ${this.key}, ${this.value}${trailer})`
}
}

View File

@@ -15,9 +15,9 @@ export default class MacroGraphReferenceEntity extends IEntity {
constructor(values) {
super(values)
/** @type {ObjectReferenceEntity} */ this.MacroGraph
/** @type {ObjectReferenceEntity} */ this.GraphBlueprint
/** @type {GuidEntity} */ this.GuidEntity
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.MacroGraph>} */ this.MacroGraph
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.GraphBlueprint>} */ this.GraphBlueprint
/** @type {InstanceType<typeof MacroGraphReferenceEntity.attributes.GraphGuid>} */ this.GraphGuid
}
getMacroName() {

View File

@@ -6,7 +6,7 @@ export default class MirroredEntity extends IEntity {
/** @type {typeof IEntity} */
static type
/** @param {() => T} getter */
/** @param {() => InstanceType<T>} getter */
constructor(getter = null) {
super()
this.getter = getter
@@ -32,7 +32,11 @@ export default class MirroredEntity extends IEntity {
return result
}
toString() {
return this.getter().toString()
toString(
insideString = false,
indentation = "",
printKey = this.Self().printKey,
) {
return this.getter().toString(insideString, indentation, printKey)
}
}

View File

@@ -1,13 +1,14 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class NumberEntity extends IEntity {
static grammar = P.regArray(
new RegExp(`(${P.number.getParser().parser.regexp.source})|(\\+?inf)|(-inf)`)
new RegExp(`(${Grammar.numberRegexSource})|(\\+?inf)|(-inf)`)
).map(([_0, n, plusInf, minusInf]) => new this(
n ? Number(n) : plusInf ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY
))
)).label("NumberEntity")
/** @type {Number} */
#value
@@ -31,6 +32,12 @@ export default class NumberEntity extends IEntity {
}
toString() {
if (this.value === Number.POSITIVE_INFINITY) {
return "+inf"
}
if (this.value === Number.NEGATIVE_INFINITY) {
return "-inf"
}
return this.value.toString()
}
}

View File

@@ -28,12 +28,14 @@ import VariableReferenceEntity from "./VariableReferenceEntity.js"
export default class ObjectEntity extends IEntity {
#_exported = false
get _exported() {
return this.#_exported
static trailing = true
#exported = false
get exported() {
return this.#exported
}
set _exported(value) {
this.#_exported = value
set exported(value) {
this.#exported = value
}
static attributes = {
@@ -130,7 +132,7 @@ export default class ObjectEntity extends IEntity {
ScriptVariables: ArrayEntity.of(ScriptVariableEntity),
Node: MirroredEntity.of(ObjectReferenceEntity),
ExportedNodes: StringEntity,
CustomProperties: ArrayEntity.of(AlternativesEntity.accepting(PinEntity, UnknownPinEntity)),
CustomProperties: ArrayEntity.of(AlternativesEntity.accepting(PinEntity, UnknownPinEntity)).withDefault().flagSilent(),
}
static #nameRegex = /^(\w+?)(?:_(\d+))?$/
static customPropertyGrammar = P.seq(
@@ -144,28 +146,28 @@ export default class ObjectEntity extends IEntity {
Grammar.symbolQuoted.map(v => [v, true]),
Grammar.symbol.map(v => [v, false]),
),
P.reg(
new RegExp(`\\s*\\(\\s*(\\d+)\\s*\\)\\s*\\=\\s*`),
1
).map(Number)
P.reg(new RegExp(String.raw`\s*\(\s*(\d+)\s*\)\s*\=\s*`), 1).map(Number)
)
.chain(
/** @param {[[String, Boolean], Number]} param */
/** @param {[[keyof ObjectEntity.attributes, Boolean], Number]} param */
([[symbol, quoted], index]) =>
Grammar.grammarFor(this.attributes[symbol])
.map(currentValue =>
values => {
(values[symbol] ??= [])[index] = currentValue
Utility.objectSet(values, ["attributes", symbol, "quoted"], quoted)
if (!this.attributes[symbol]?.inlined) {
if (!values.attributes) {
IEntity.defineAttributes(values, {})
}
Utility.objectSet(values, ["attributes", symbol, "type"], [currentValue.constructor])
Utility.objectSet(values, ["attributes", symbol, "inlined"], true)
this.attributes[symbol].grammar.map(currentValue =>
values => {
if (values[symbol] === undefined) {
let arrayEntity = ArrayEntity
if (quoted != arrayEntity.quoted) {
arrayEntity = arrayEntity.flagQuoted(quoted)
}
if (!arrayEntity.inlined) {
arrayEntity = arrayEntity.flagInlined()
}
values[symbol] = new arrayEntity()
}
)
/** @type {ArrayEntity} */
const target = values[symbol]
target.values[index] = currentValue
}
)
)
static grammar = this.createGrammar()
@@ -233,73 +235,71 @@ export default class ObjectEntity extends IEntity {
super(values)
// Attributes
/** @type {(PinEntity | UnknownPinEntity)[]} */ this.CustomProperties
/** @type {Boolean} */ this.bIsPureFunc
/** @type {Boolean} */ this.isExported
/** @type {FunctionReferenceEntity} */ this.ComponentPropertyName
/** @type {FunctionReferenceEntity} */ this.EventReference
/** @type {FunctionReferenceEntity} */ this.FunctionReference
/** @type {IdentifierEntity} */ this.AdvancedPinDisplay
/** @type {IdentifierEntity} */ this.EnabledState
/** @type {IntegerEntity} */ this.NodeHeight
/** @type {IntegerEntity} */ this.NodePosX
/** @type {IntegerEntity} */ this.NodePosY
/** @type {IntegerEntity} */ this.NodeWidth
/** @type {LinearColorEntity} */ this.CommentColor
/** @type {LinearColorEntity} */ this.NodeTitleColor
/** @type {MacroGraphReferenceEntity} */ this.MacroGraphReference
/** @type {MirroredEntity} */ this.MaterialExpressionEditorX
/** @type {MirroredEntity} */ this.MaterialExpressionEditorY
/** @type {MirroredEntity} */ this.SizeX
/** @type {MirroredEntity} */ this.SizeY
/** @type {MirroredEntity} */ this.Text
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionX
/** @type {MirroredEntity<IntegerEntity>} */ this.PositionY
/** @type {MirroredEntity<ObjectReferenceEntity>} */ this.Node
/** @type {null[]} */ this.PinTags
/** @type {Number} */ this.NumAdditionalInputs
/** @type {ObjectReferenceEntity[]} */ this.InputPins
/** @type {ObjectReferenceEntity[]} */ this.OutputPins
/** @type {ObjectReferenceEntity} */ this.Archetype
/** @type {ObjectReferenceEntity} */ this.BlueprintElementInstance
/** @type {ObjectReferenceEntity} */ this.BlueprintElementType
/** @type {ObjectReferenceEntity} */ this.Class
/** @type {ObjectReferenceEntity} */ this.Enum
/** @type {ObjectReferenceEntity} */ this.ExportPath
/** @type {ObjectReferenceEntity} */ this.FunctionScript
/** @type {ObjectReferenceEntity} */ this.Graph
/** @type {ObjectReferenceEntity} */ this.MaterialExpression
/** @type {ObjectReferenceEntity} */ this.MaterialExpressionComment
/** @type {ObjectReferenceEntity} */ this.MaterialFunction
/** @type {ObjectReferenceEntity} */ this.ObjectRef
/** @type {ObjectReferenceEntity} */ this.PCGNode
/** @type {ObjectReferenceEntity} */ this.SettingsInterface
/** @type {ObjectReferenceEntity} */ this.StructType
/** @type {ObjectReferenceEntity} */ this.TargetType
/** @type {ScriptVariableEntity[]} */ this.ScriptVariables
/** @type {String[]} */ this.EnumEntries
/** @type {String[]} */ this.PinNames
/** @type {String} */ this.CustomFunctionName
/** @type {String} */ this.DelegatePropertyName
/** @type {String} */ this.ExportedNodes
/** @type {String} */ this.FunctionDisplayName
/** @type {String} */ this.InputName
/** @type {String} */ this.Name
/** @type {String} */ this.NodeComment
/** @type {String} */ this.NodeTitle
/** @type {String} */ this.Operation
/** @type {String} */ this.OpName
/** @type {String} */ this.ProxyFactoryFunctionName
/** @type {String} */ this.SubgraphInstance
/** @type {String} */ this.Text
/** @type {SymbolEntity} */ this.AxisKey
/** @type {SymbolEntity} */ this.HiGenGridSize
/** @type {SymbolEntity} */ this.InputAxisKey
/** @type {SymbolEntity} */ this.InputKey
/** @type {SymbolEntity} */ this.InputType
/** @type {UnknownPinEntity[]} */ this.AddedPins
/** @type {VariableReferenceEntity} */ this.DelegateReference
/** @type {VariableReferenceEntity} */ this.VariableReference
/** @type {InstanceType<typeof ObjectEntity.attributes.AddedPins>} */ this.AddedPins
/** @type {InstanceType<typeof ObjectEntity.attributes.AdvancedPinDisplay>} */ this.AdvancedPinDisplay
/** @type {InstanceType<typeof ObjectEntity.attributes.Archetype>} */ this.Archetype
/** @type {InstanceType<typeof ObjectEntity.attributes.AxisKey>} */ this.AxisKey
/** @type {InstanceType<typeof ObjectEntity.attributes.bIsPureFunc>} */ this.bIsPureFunc
/** @type {InstanceType<typeof ObjectEntity.attributes.BlueprintElementInstance>} */ this.BlueprintElementInstance
/** @type {InstanceType<typeof ObjectEntity.attributes.BlueprintElementType>} */ this.BlueprintElementType
/** @type {InstanceType<typeof ObjectEntity.attributes.Class>} */ this.Class
/** @type {InstanceType<typeof ObjectEntity.attributes.CommentColor>} */ this.CommentColor
/** @type {InstanceType<typeof ObjectEntity.attributes.ComponentPropertyName>} */ this.ComponentPropertyName
/** @type {InstanceType<typeof ObjectEntity.attributes.CustomFunctionName>} */ this.CustomFunctionName
/** @type {InstanceType<typeof ObjectEntity.attributes.CustomProperties>} */ this.CustomProperties
/** @type {InstanceType<typeof ObjectEntity.attributes.DelegatePropertyName>} */ this.DelegatePropertyName
/** @type {InstanceType<typeof ObjectEntity.attributes.DelegateReference>} */ this.DelegateReference
/** @type {InstanceType<typeof ObjectEntity.attributes.EnabledState>} */ this.EnabledState
/** @type {InstanceType<typeof ObjectEntity.attributes.Enum>} */ this.Enum
/** @type {InstanceType<typeof ObjectEntity.attributes.EnumEntries>} */ this.EnumEntries
/** @type {InstanceType<typeof ObjectEntity.attributes.EventReference>} */ this.EventReference
/** @type {InstanceType<typeof ObjectEntity.attributes.ExportedNodes>} */ this.ExportedNodes
/** @type {InstanceType<typeof ObjectEntity.attributes.ExportPath>} */ this.ExportPath
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionDisplayName>} */ this.FunctionDisplayName
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionReference>} */ this.FunctionReference
/** @type {InstanceType<typeof ObjectEntity.attributes.FunctionScript>} */ this.FunctionScript
/** @type {InstanceType<typeof ObjectEntity.attributes.Graph>} */ this.Graph
/** @type {InstanceType<typeof ObjectEntity.attributes.HiGenGridSize>} */ this.HiGenGridSize
/** @type {InstanceType<typeof ObjectEntity.attributes.InputAxisKey>} */ this.InputAxisKey
/** @type {InstanceType<typeof ObjectEntity.attributes.InputKey>} */ this.InputKey
/** @type {InstanceType<typeof ObjectEntity.attributes.InputName>} */ this.InputName
/** @type {InstanceType<typeof ObjectEntity.attributes.InputPins>} */ this.InputPins
/** @type {InstanceType<typeof ObjectEntity.attributes.InputType>} */ this.InputType
/** @type {InstanceType<typeof ObjectEntity.attributes.MacroGraphReference>} */ this.MacroGraphReference
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpression>} */ this.MaterialExpression
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionComment>} */ this.MaterialExpressionComment
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionEditorX>} */ this.MaterialExpressionEditorX
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialExpressionEditorY>} */ this.MaterialExpressionEditorY
/** @type {InstanceType<typeof ObjectEntity.attributes.MaterialFunction>} */ this.MaterialFunction
/** @type {InstanceType<typeof ObjectEntity.attributes.Name>} */ this.Name
/** @type {InstanceType<typeof ObjectEntity.attributes.Node>} */ this.Node
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeComment>} */ this.NodeComment
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeHeight>} */ this.NodeHeight
/** @type {InstanceType<typeof ObjectEntity.attributes.NodePosX>} */ this.NodePosX
/** @type {InstanceType<typeof ObjectEntity.attributes.NodePosY>} */ this.NodePosY
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeTitle>} */ this.NodeTitle
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeTitleColor>} */ this.NodeTitleColor
/** @type {InstanceType<typeof ObjectEntity.attributes.NodeWidth>} */ this.NodeWidth
/** @type {InstanceType<typeof ObjectEntity.attributes.NumAdditionalInputs>} */ this.NumAdditionalInputs
/** @type {InstanceType<typeof ObjectEntity.attributes.ObjectRef>} */ this.ObjectRef
/** @type {InstanceType<typeof ObjectEntity.attributes.Operation>} */ this.Operation
/** @type {InstanceType<typeof ObjectEntity.attributes.OpName>} */ this.OpName
/** @type {InstanceType<typeof ObjectEntity.attributes.OutputPins>} */ this.OutputPins
/** @type {InstanceType<typeof ObjectEntity.attributes.PCGNode>} */ this.PCGNode
/** @type {InstanceType<typeof ObjectEntity.attributes.PinNames>} */ this.PinNames
/** @type {InstanceType<typeof ObjectEntity.attributes.PositionX>} */ this.PositionX
/** @type {InstanceType<typeof ObjectEntity.attributes.PositionY>} */ this.PositionY
/** @type {InstanceType<typeof ObjectEntity.attributes.ProxyFactoryFunctionName>} */ this.ProxyFactoryFunctionName
/** @type {InstanceType<typeof ObjectEntity.attributes.ScriptVariables>} */ this.ScriptVariables
/** @type {InstanceType<typeof ObjectEntity.attributes.SettingsInterface>} */ this.SettingsInterface
/** @type {InstanceType<typeof ObjectEntity.attributes.SizeX>} */ this.SizeX
/** @type {InstanceType<typeof ObjectEntity.attributes.SizeY>} */ this.SizeY
/** @type {InstanceType<typeof ObjectEntity.attributes.StructType>} */ this.StructType
/** @type {InstanceType<typeof ObjectEntity.attributes.SubgraphInstance>} */ this.SubgraphInstance
/** @type {InstanceType<typeof ObjectEntity.attributes.TargetType>} */ this.TargetType
/** @type {InstanceType<typeof ObjectEntity.attributes.Text>} */ this.Text
/** @type {InstanceType<typeof ObjectEntity.attributes.Text>} */ this.Text
/** @type {InstanceType<typeof ObjectEntity.attributes.VariableReference>} */ this.VariableReference
// Legacy nodes pins
if (this["Pins"] instanceof Array) {
@@ -481,10 +481,7 @@ export default class ObjectEntity extends IEntity {
}
getCustomproperties(canCreate = false) {
if (canCreate && !this.CustomProperties) {
this.CustomProperties = []
}
return this.CustomProperties ?? []
return this.CustomProperties.values
}
/** @returns {PinEntity[]} */
@@ -615,4 +612,44 @@ export default class ObjectEntity extends IEntity {
additionalPinInserter() {
return nodeVariadic(this)
}
/** @param {String} key */
showProperty(key) {
switch (key) {
case "Class":
case "Name":
case "Archetype":
case "ExportPath":
case "CustomProperties":
// Serielized separately, check doWrite()
return false
}
return super.showProperty(key)
}
toString(
insideString = false,
indentation = "",
printKey = this.Self().printKey,
) {
const moreIndentation = indentation + Configuration.indentation
let result = indentation + "Begin Object"
+ (this.Class?.type || this.Class?.path ? ` Class=${this.Class.toString(insideString)}` : "")
+ (this.Name ? ` Name=${this.Name.toString(insideString)}` : "")
+ (this.Archetype ? ` Archetype=${this.Archetype.toString(insideString)}` : "")
+ (this.ExportPath?.type || this.ExportPath?.path ? ` ExportPath=${this.ExportPath.toString(insideString)}` : "")
+ "\n"
+ super.toString(insideString, moreIndentation, k => this[k] instanceof ObjectEntity ? "" : k)
+ (!this.CustomProperties.Self().ignored
? this.getCustomproperties().map(pin =>
moreIndentation
+ printKey("CustomProperties ")
+ pin.toString(insideString)
+ this.Self().attributeSeparator
).join("")
: ""
)
+ indentation + "End Object"
return result
}
}

View File

@@ -11,11 +11,14 @@ export default class ObjectReferenceEntity extends IEntity {
+ `'(${Grammar.Regex.InsideSingleQuotedString.source})'`
)).map(([_0, a, b]) => a ?? b)
static typeReference = P.reg(
// @ts-expect-error
new RegExp(Grammar.Regex.Path.source + "|" + Grammar.symbol.getParser().regexp.source)
)
static fullReferenceGrammar = P.regArray(
new RegExp(
// @ts-expect-error
"(" + this.typeReference.getParser().regexp.source + ")"
// @ts-expect-error
+ "(?:" + this.#quotedParser.getParser().parser.regexp.source + ")"
)
).map(([full, type, ...path]) => new this(type, path.find(v => v), full))
@@ -30,7 +33,7 @@ export default class ObjectReferenceEntity extends IEntity {
this.fullReferenceSerializedGrammar,
this.fullReferenceGrammar,
this.typeReferenceGrammar,
)
).label("ObjectReferenceEntity")
#type
get type() {
@@ -72,7 +75,11 @@ export default class ObjectReferenceEntity extends IEntity {
return Utility.getNameFromPath(this.path.replace(/_C$/, ""), dropCounter)
}
toString() {
toString(
insideString = false,
indentation = "",
printKey = this.Self().printKey,
) {
return this.full
}
}

View File

@@ -1,20 +0,0 @@
import Grammar from "../serialization/Grammar.js"
import IEntity from "./IEntity.js"
export default class PathSymbolEntity extends IEntity {
static grammar = Grammar.symbol.map(v => new this(v))
constructor(value = "") {
super()
this.value = value
}
valueOf() {
return this.value
}
toString() {
return this.value.toString()
}
}

View File

@@ -32,7 +32,7 @@ import Vector2DEntity from "./Vector2DEntity.js"
import Vector4DEntity from "./Vector4DEntity.js"
import VectorEntity from "./VectorEntity.js"
/** @template {TerminalAttribute} T */
/** @template {IEntity} T */
export default class PinEntity extends IEntity {
static lookbehind = "INVTEXT"
@@ -120,25 +120,23 @@ export default class PinEntity extends IEntity {
constructor(values = {}) {
super(values)
/** @type {ObjectEntity} */ this.objectEntity
/** @type {Number} */ this.pinIndex
/** @type {GuidEntity} */ this.PinId
/** @type {String} */ this.PinName
/** @type {LocalizedTextEntity | String} */ this.PinFriendlyName
/** @type {String} */ this.PinToolTip
/** @type {String} */ this.Direction
/** @type {PinTypeEntity} */ this.PinType
/** @type {PinReferenceEntity[]} */ this.LinkedTo
/** @type {T} */ this.DefaultValue
/** @type {String} */ this.AutogeneratedDefaultValue
/** @type {ObjectReferenceEntity} */ this.DefaultObject
/** @type {GuidEntity} */ this.PersistentGuid
/** @type {Boolean} */ this.bHidden
/** @type {Boolean} */ this.bNotConnectable
/** @type {Boolean} */ this.bDefaultValueIsReadOnly
/** @type {Boolean} */ this.bDefaultValueIsIgnored
/** @type {Boolean} */ this.bAdvancedView
/** @type {Boolean} */ this.bOrphanedPin
/** @type {InstanceType<typeof PinEntity.attributes.PinId>} */ this.PinId
/** @type {InstanceType<typeof PinEntity.attributes.PinName>} */ this.PinName
/** @type {InstanceType<typeof PinEntity.attributes.PinFriendlyName>} */ this.PinFriendlyName
/** @type {InstanceType<typeof PinEntity.attributes.PinToolTip>} */ this.PinToolTip
/** @type {InstanceType<typeof PinEntity.attributes.Direction>} */ this.Direction
/** @type {InstanceType<typeof PinEntity.attributes.PinType>} */ this.PinType
/** @type {InstanceType<typeof PinEntity.attributes.LinkedTo>} */ this.LinkedTo
/** @type {InstanceType<typeof PinEntity.attributes.DefaultValue>} */ this.DefaultValue
/** @type {InstanceType<typeof PinEntity.attributes.AutogeneratedDefaultValue>} */ this.AutogeneratedDefaultValue
/** @type {InstanceType<typeof PinEntity.attributes.DefaultObject>} */ this.DefaultObject
/** @type {InstanceType<typeof PinEntity.attributes.PersistentGuid>} */ this.PersistentGuid
/** @type {InstanceType<typeof PinEntity.attributes.bHidden>} */ this.bHidden
/** @type {InstanceType<typeof PinEntity.attributes.bNotConnectable>} */ this.bNotConnectable
/** @type {InstanceType<typeof PinEntity.attributes.bDefaultValueIsReadOnly>} */ this.bDefaultValueIsReadOnly
/** @type {InstanceType<typeof PinEntity.attributes.bDefaultValueIsIgnored>} */ this.bDefaultValueIsIgnored
/** @type {InstanceType<typeof PinEntity.attributes.bAdvancedView>} */ this.bAdvancedView
/** @type {InstanceType<typeof PinEntity.attributes.bOrphanedPin>} */ this.bOrphanedPin
}
/** @param {ObjectEntity} objectEntity */
@@ -227,7 +225,6 @@ export default class PinEntity extends IEntity {
getDefaultValue(maybeCreate = false) {
if (this.DefaultValue === undefined && maybeCreate) {
// @ts-expect-error
this.DefaultValue = new (this.getEntityType(true))()
}
return this.DefaultValue
@@ -271,10 +268,7 @@ export default class PinEntity extends IEntity {
&& pinReferenceEntity.pinGuid.valueOf() == targetPinEntity.PinId.valueOf()
)
if (!linkFound) {
(this.LinkedTo ??= []).push(new PinReferenceEntity({
objectName: targetObjectName,
pinGuid: targetPinEntity.PinId,
}))
(this.LinkedTo ??= []).push(new PinReferenceEntity(targetObjectName, targetPinEntity.PinId,))
return true
}
return false // Already linked

View File

@@ -1,18 +1,20 @@
import P from "parsernostrum"
import GuidEntity from "./GuidEntity.js"
import IEntity from "./IEntity.js"
import PathSymbolEntity from "./PathSymbolEntity.js"
import SymbolEntity from "./SymbolEntity.js"
export default class PinReferenceEntity extends IEntity {
static grammar = P.seq(
PathSymbolEntity.grammar,
SymbolEntity.grammar,
P.whitespace,
GuidEntity.grammar
).map(([objectName, _1, pinGuid]) => new this(objectName, pinGuid))
)
.map(([objectName, _1, pinGuid]) => new this(objectName, pinGuid))
.label("PinReferenceEntity")
/**
* @param {PathSymbolEntity} objectName
* @param {SymbolEntity} objectName
* @param {GuidEntity} pinGuid
*/
constructor(objectName = null, pinGuid = null) {
@@ -20,4 +22,12 @@ export default class PinReferenceEntity extends IEntity {
this.objectName = objectName
this.pinGuid = pinGuid
}
toString(
insideString = false,
indentation = "",
printKey = this.Self().printKey,
) {
return this.objectName.toString() + " " + this.pinGuid.toString()
}
}

View File

@@ -3,8 +3,8 @@ import BooleanEntity from "./BooleanEntity.js"
import FunctionReferenceEntity from "./FunctionReferenceEntity.js"
import IEntity from "./IEntity.js"
import ObjectReferenceEntity from "./ObjectReferenceEntity.js"
import PathSymbolEntity from "./PathSymbolEntity.js"
import StringEntity from "./StringEntity.js"
import SymbolEntity from "./SymbolEntity.js"
export default class PinTypeEntity extends IEntity {
@@ -15,29 +15,29 @@ export default class PinTypeEntity extends IEntity {
PinSubCategoryObject: ObjectReferenceEntity.withDefault(),
PinSubCategoryMemberReference: FunctionReferenceEntity.withDefault(type => null),
PinValueType: PinTypeEntity.withDefault(),
ContainerType: PathSymbolEntity,
ContainerType: SymbolEntity,
bIsReference: BooleanEntity.withDefault(),
bIsConst: BooleanEntity.withDefault(),
bIsWeakPointer: BooleanEntity.withDefault(),
bIsUObjectWrapper: BooleanEntity.withDefault(),
bSerializeAsSinglePrecisionFloat: BooleanEntity.withDefault(),
}
static grammar = Grammar.createEntityGrammar(this)
static grammar = Grammar.createEntityGrammar(this).label("PinTypeEntity")
constructor(values = {}) {
super(values)
/** @type {String} */ this.PinCategory
/** @type {String} */ this.PinSubCategory
/** @type {ObjectReferenceEntity} */ this.PinSubCategoryObject
/** @type {FunctionReferenceEntity} */ this.PinSubCategoryMemberReference
/** @type {PinTypeEntity} */ this.PinValueType
/** @type {PathSymbolEntity} */ this.ContainerType
/** @type {Boolean} */ this.bIsReference
/** @type {Boolean} */ this.bIsConst
/** @type {Boolean} */ this.bIsWeakPointer
/** @type {Boolean} */ this.bIsUObjectWrapper
/** @type {Boolean} */ this.bIsUObjectWrapper
/** @type {Boolean} */ this.bSerializeAsSinglePrecisionFloat
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinCategory>} */ this.PinCategory
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategory>} */ this.PinSubCategory
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategoryObject>} */ this.PinSubCategoryObject
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinSubCategoryMemberReference>} */ this.PinSubCategoryMemberReference
/** @type {InstanceType<typeof PinTypeEntity.attributes.PinValueType>} */ this.PinValueType
/** @type {InstanceType<typeof PinTypeEntity.attributes.ContainerType>} */ this.ContainerType
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsReference>} */ this.bIsReference
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsConst>} */ this.bIsConst
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsWeakPointer>} */ this.bIsWeakPointer
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsUObjectWrapper>} */ this.bIsUObjectWrapper
/** @type {InstanceType<typeof PinTypeEntity.attributes.bIsUObjectWrapper>} */ this.bIsUObjectWrapper
/** @type {InstanceType<typeof PinTypeEntity.attributes.bSerializeAsSinglePrecisionFloat>} */ this.bSerializeAsSinglePrecisionFloat
}
/** @param {PinTypeEntity} other */

View File

@@ -1,17 +1,18 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import Vector2DEntity from "./Vector2DEntity.js"
export default class RBSerializationVector2DEntity extends Vector2DEntity {
static grammar = P.alt(
P.regArray(new RegExp(
/X\s*=\s*/.source + "(?<x>" + P.number.getParser().parser.regexp.source + ")"
/X\s*=\s*/.source + "(?<x>" + Grammar.numberRegexSource + ")"
+ "\\s+"
+ /Y\s*=\s*/.source + "(?<y>" + P.number.getParser().parser.regexp.source + ")"
+ /Y\s*=\s*/.source + "(?<y>" + Grammar.numberRegexSource + ")"
)).map(({ groups: { x, y } }) => new this({
X: Number(x),
Y: Number(y),
})),
Vector2DEntity.grammar
)
).label("RBSerializationVector2DEntity")
}

View File

@@ -10,13 +10,13 @@ export default class RotatorEntity extends IEntity {
P: NumberEntity.withDefault(),
Y: NumberEntity.withDefault(),
}
static grammar = Grammar.createEntityGrammar(this, false)
static grammar = Grammar.createEntityGrammar(this).label("RotatorEntity")
constructor(values) {
super(values)
/** @type {NumberEntity} */ this.R
/** @type {NumberEntity} */ this.P
/** @type {NumberEntity} */ this.Y
/** @type {InstanceType<typeof RotatorEntity.attributes.R>} */ this.R
/** @type {InstanceType<typeof RotatorEntity.attributes.P>} */ this.P
/** @type {InstanceType<typeof RotatorEntity.attributes.Y>} */ this.Y
}
getRoll() {

View File

@@ -10,11 +10,11 @@ export default class ScriptVariableEntity extends IEntity {
ScriptVariable: ObjectReferenceEntity,
OriginalChangeId: GuidEntity,
}
static grammar = Grammar.createEntityGrammar(this)
static grammar = Grammar.createEntityGrammar(this).label("ScriptVariableEntity")
constructor(values = {}) {
super(values)
/** @type {ObjectReferenceEntity} */ this.ScriptVariable
/** @type {GuidEntity} */ this.OriginalChangeId
/** @type {InstanceType<typeof ScriptVariableEntity.attributes.ScriptVariable>} */ this.ScriptVariable
/** @type {InstanceType<typeof ScriptVariableEntity.attributes.OriginalChangeId>} */ this.OriginalChangeId
}
}

View File

@@ -1,15 +1,16 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import RotatorEntity from "./RotatorEntity.js"
export default class SimpleSerializationRotatorEntity extends RotatorEntity {
static grammar = P.alt(
P.regArray(new RegExp(
`(${P.number.getParser().parser.regexp.source})`
`(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
)).map(([_, p, y, r]) => new this({
R: Number(r),
P: Number(p),

View File

@@ -1,13 +1,14 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import Vector2DEntity from "./Vector2DEntity.js"
export default class SimpleSerializationVector2DEntity extends Vector2DEntity {
static grammar = P.alt(
P.regArray(new RegExp(
`(${P.number.getParser().parser.regexp.source})`
`(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
)).map(([_, x, y]) => new this({
X: Number(x),
Y: Number(y),

View File

@@ -1,4 +1,5 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import Vector4DEntity from "./Vector4DEntity.js"
export default class SimpleSerializationVector4DEntity extends Vector4DEntity {
@@ -6,16 +7,16 @@ export default class SimpleSerializationVector4DEntity extends Vector4DEntity {
static grammar = this.createGrammar()
static createGrammar() {
const number = P.number.getParser().parser.regexp.source
const number = Grammar.numberRegexSource
return P.alt(
P.regArray(new RegExp(
`(${P.number.getParser().parser.regexp.source})`
`(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
))
.map(([_0, x, y, z, w]) => new this({
X: Number(x),

View File

@@ -1,15 +1,16 @@
import P from "parsernostrum"
import Grammar from "../serialization/Grammar.js"
import VectorEntity from "./VectorEntity.js"
export default class SimpleSerializationVectorEntity extends VectorEntity {
static grammar = P.alt(
P.regArray(new RegExp(
`(${P.number.getParser().parser.regexp.source})`
`(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
+ String.raw`\s*,\s*`
+ `(${P.number.getParser().parser.regexp.source})`
+ `(${Grammar.numberRegexSource})`
))
.map(([_0, x, y, z]) => new this({
X: Number(x),

View File

@@ -1,10 +1,12 @@
import P from "parsernostrum"
import IEntity from "./IEntity.js"
import Utility from "../Utility.js"
import IPrintableEntity from "./IPrintableEntity.js"
export default class StringEntity extends IEntity {
export default class StringEntity extends IPrintableEntity {
static grammar = P.doubleQuotedString.map(insideString => Utility.unescapeString(insideString))
static grammar = P.doubleQuotedString
.map(insideString => new this(Utility.unescapeString(insideString)))
.label("StringEntity")
/** @param {String} value */
constructor(value = "") {
@@ -12,11 +14,19 @@ export default class StringEntity extends IEntity {
this.value = value
}
print() {
return this.value
}
valueOf() {
return this.value
}
toString() {
return this.value.toString()
toString(insideString = false) {
let result = Utility.escapeString(this.value)
if (!insideString) {
result = `"${result}"`
}
return result
}
}

View File

@@ -3,7 +3,7 @@ import IEntity from "./IEntity.js"
export default class SymbolEntity extends IEntity {
static grammar = Grammar.symbol.map(v => new this(v))
static grammar = Grammar.symbol.map(v => new this(v)).label("SymbolEntity")
/** @param {String} value */
constructor(value = "") {

View File

@@ -4,7 +4,6 @@ import IEntity from "./IEntity.js"
export default class UnknownKeysEntity extends IEntity {
static grammar = P.seq(
// Lookbehind
P.reg(new RegExp(`(${Grammar.Regex.Path.source}|${Grammar.Regex.Symbol.source}\\s*)?\\(\\s*`), 1),
@@ -24,7 +23,7 @@ export default class UnknownKeysEntity extends IEntity {
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}).label("UnknownKeysEntity")
constructor(values = {}) {
super(values)

View File

@@ -16,5 +16,5 @@ export default class UnknownPinEntity extends PinEntity {
}
attributes.forEach(attributeSetter => attributeSetter(values))
return new this(values)
})
}).label("UnknownPinEntity")
}

View File

@@ -13,12 +13,13 @@ export default class VariableReferenceEntity extends IEntity {
MemberGuid: GuidEntity,
bSelfContext: BooleanEntity,
}
static grammar = Grammar.createEntityGrammar(this)
static grammar = Grammar.createEntityGrammar(this).label("VariableReferenceEntity")
constructor(values) {
super(values)
/** @type {String} */ this.MemberName
/** @type {GuidEntity} */ this.GuidEntity
/** @type {Boolean} */ this.bSelfContext
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberScope>} */ this.MemberScope
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberName>} */ this.MemberName
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.MemberGuid>} */ this.MemberGuid
/** @type {InstanceType<typeof VariableReferenceEntity.attributes.bSelfContext>} */ this.bSelfContext
}
}

View File

@@ -9,12 +9,12 @@ export default class Vector2DEntity extends IEntity {
X: NumberEntity.withDefault(),
Y: NumberEntity.withDefault(),
}
static grammar = Grammar.createEntityGrammar(this, false)
static grammar = Grammar.createEntityGrammar(this).label("Vector2DEntity")
constructor(values) {
super(values)
/** @type {NumberEntity} */ this.X
/** @type {NumberEntity} */ this.Y
/** @type {InstanceType<typeof Vector2DEntity.attributes.X>} */ this.X
/** @type {InstanceType<typeof Vector2DEntity.attributes.Y>} */ this.Y
}
/** @returns {[Number, Number]} */

View File

@@ -11,14 +11,14 @@ export default class Vector4DEntity extends IEntity {
Z: NumberEntity.withDefault(),
W: NumberEntity.withDefault(),
}
static grammar = Grammar.createEntityGrammar(Vector4DEntity, false)
static grammar = Grammar.createEntityGrammar(this).label("Vector4DEntity")
constructor(values) {
super(values)
/** @type {NumberEntity} */ this.X
/** @type {NumberEntity} */ this.Y
/** @type {NumberEntity} */ this.Z
/** @type {NumberEntity} */ this.W
/** @type {InstanceType<typeof Vector4DEntity.attributes.X>} */ this.X
/** @type {InstanceType<typeof Vector4DEntity.attributes.Y>} */ this.Y
/** @type {InstanceType<typeof Vector4DEntity.attributes.Z>} */ this.Z
/** @type {InstanceType<typeof Vector4DEntity.attributes.W>} */ this.W
}
/** @returns {[Number, Number, Number, Number]} */

View File

@@ -10,13 +10,13 @@ export default class VectorEntity extends IEntity {
Y: NumberEntity.withDefault(),
Z: NumberEntity.withDefault(),
}
static grammar = Grammar.createEntityGrammar(VectorEntity, false)
static grammar = Grammar.createEntityGrammar(this).label("VectorEntity")
constructor(values) {
super(values)
/** @type {NumberEntity} */ this.X
/** @type {NumberEntity} */ this.Y
/** @type {NumberEntity} */ this.Z
/** @type {InstanceType<typeof VectorEntity.attributes.X>} */ this.X
/** @type {InstanceType<typeof VectorEntity.attributes.Y>} */ this.Y
/** @type {InstanceType<typeof VectorEntity.attributes.X>} */ this.Z
}
/** @returns {[Number, Number, Number]} */

View File

@@ -8,6 +8,10 @@ import Serializable from "./Serializable.js"
export default class Grammar {
/** @type {String} */
// @ts-expect-error
static numberRegexSource = Parsernostrum.number.getParser().parser.regexp.source
static separatedBy = (source, separator, min = 1) =>
new RegExp(
source + "(?:" + separator + source + ")"
@@ -188,46 +192,32 @@ export default class Grammar {
/**
* @template {IEntity} T
* @param {(new (...args: any) => T) & EntityConstructor} entityType
* @param {Boolean | Number} acceptUnknownKeys Number to specify the limit or true, to let it be a reasonable value
* @param {new (...args: any) => T} entityType
* @return {Parsernostrum<T>}
*/
static createEntityGrammar(entityType, acceptUnknownKeys = true, entriesSeparator = this.commaSeparation) {
const lookbehind = entityType.attributes.lookbehind.default
static createEntityGrammar(entityType, entriesSeparator = this.commaSeparation) {
const lookbehind = entityType.lookbehind instanceof Array ? entityType.lookbehind.join("|") : entityType.lookbehind
return Parsernostrum.seq(
Parsernostrum.reg(
lookbehind instanceof Union
? new RegExp(`(${lookbehind.values.reduce((acc, cur) => acc + "|" + cur)})\\s*\\(\\s*`)
: lookbehind.constructor == String && lookbehind.length > 0
? new RegExp(`(${lookbehind})\\s*\\(\\s*`)
: /()\(\s*/,
1
),
Parsernostrum.reg(new RegExp(String.raw`(${lookbehind})\s*\(\s*`), 1),
this.createAttributeGrammar(entityType).sepBy(entriesSeparator),
Parsernostrum.reg(/\s*(?:,\s*)?\)/), // trailing comma
Parsernostrum.reg(/\s*(,\s*)?\)/, 1), // optional trailing comma
)
.map(([lookbehind, attributes, _2]) => {
.map(([lookbehind, attributes, trailing]) => {
let values = {}
attributes.forEach(attributeSetter => attributeSetter(values))
if (lookbehind.length) {
values.lookbehind = lookbehind
values["#lookbehind"] = lookbehind
}
attributes.forEach(attributeSetter => attributeSetter(values))
values["#trailing"] = trailing !== undefined
return values
})
// Decide if we accept the entity or not. It is accepted if it doesn't have too many unexpected keys
.chain(values => {
let totalKeys = Object.keys(values)
let missingKey
// Check missing values
if (
Object.keys(/** @type {AttributeDeclarations} */(entityType.attributes))
.filter(key => entityType.attributes[key].expected)
.find(key => !totalKeys.includes(key) && (missingKey = key))
) {
return Parsernostrum.failure()
if (entityType.lookbehind instanceof Array || entityType.lookbehind !== lookbehind) {
entityType = entityType.withLookbehind(lookbehind)
}
const unknownKeys = Object.keys(values).filter(key => !(key in entityType.attributes)).length
if (!acceptUnknownKeys && unknownKeys > 0) {
return Parsernostrum.failure()
if (entityType.trailing !== values["#trailing"]) {
entityType = entityType.flagTrailing(values["#trailing"])
}
return Parsernostrum.success().map(() => new entityType(values))
})

View File

@@ -19,7 +19,6 @@ import MacroGraphReferenceEntity from "../entity/MacroGraphReferenceEntity.js"
import MirroredEntity from "../entity/MirroredEntity.js"
import ObjectEntity from "../entity/ObjectEntity.js"
import ObjectReferenceEntity from "../entity/ObjectReferenceEntity.js"
import PathSymbolEntity from "../entity/PathSymbolEntity.js"
import PinEntity from "../entity/PinEntity.js"
import PinReferenceEntity from "../entity/PinReferenceEntity.js"
import PinTypeEntity from "../entity/PinTypeEntity.js"
@@ -49,34 +48,34 @@ import StringEntity from "../entity/StringEntity.js"
import ArrayEntity from "../entity/ArrayEntity.js"
import AlternativesEntity from "../entity/AlternativesEntity.js"
Grammar.unknownValue =
Parsernostrum.alt(
// Remember to keep the order, otherwise parsing might fail
BooleanEntity.grammar,
GuidEntity.grammar,
Parsernostrum.str("None").map(() => ObjectReferenceEntity.createNoneInstance()),
Grammar.null,
NumberEntity.grammar,
ObjectReferenceEntity.fullReferenceGrammar,
StringEntity.grammar,
LocalizedTextEntity.grammar,
InvariantTextEntity.grammar,
FormatTextEntity.grammar,
PinReferenceEntity.grammar,
Vector4DEntity.grammar,
VectorEntity.grammar,
RotatorEntity.grammar,
LinearColorEntity.grammar,
Vector2DEntity.grammar,
UnknownKeysEntity.grammar,
SymbolEntity.grammar,
ArrayEntity.of(PinReferenceEntity).grammar,
ArrayEntity.of(AlternativesEntity.accepting(NumberEntity, StringEntity, SymbolEntity)).grammar,
Parsernostrum.lazy(() => ArrayEntity.createGrammar(Grammar.unknownValue)),
)
export default function initializeSerializerFactory() {
Grammar.unknownValue =
Parsernostrum.alt(
// Remember to keep the order, otherwise parsing might fail
BooleanEntity.grammar,
GuidEntity.grammar,
Parsernostrum.str("None").map(() => ObjectReferenceEntity.createNoneInstance()),
Grammar.null,
NumberEntity.grammar,
ObjectReferenceEntity.fullReferenceGrammar,
StringEntity.grammar,
LocalizedTextEntity.grammar,
InvariantTextEntity.grammar,
FormatTextEntity.grammar,
PinReferenceEntity.grammar,
Vector4DEntity.grammar,
VectorEntity.grammar,
RotatorEntity.grammar,
LinearColorEntity.grammar,
Vector2DEntity.grammar,
UnknownKeysEntity.grammar,
SymbolEntity.grammar,
ArrayEntity.of(PinReferenceEntity).grammar,
ArrayEntity.of(AlternativesEntity.accepting(NumberEntity, StringEntity, SymbolEntity)).grammar,
Parsernostrum.lazy(() => ArrayEntity.createGrammar(Grammar.unknownValue)),
)
SerializerFactory.registerSerializer(
null,
new CustomSerializer(
@@ -122,26 +121,6 @@ export default function initializeSerializerFactory() {
)
)
SerializerFactory.registerSerializer(
ByteEntity,
new ToStringSerializer(ByteEntity)
)
SerializerFactory.registerSerializer(
ColorChannelEntity,
new ToStringSerializer(ColorChannelEntity)
)
SerializerFactory.registerSerializer(
EnumDisplayValueEntity,
new ToStringSerializer(EnumDisplayValueEntity)
)
SerializerFactory.registerSerializer(
EnumEntity,
new ToStringSerializer(EnumEntity)
)
SerializerFactory.registerSerializer(
FormatTextEntity,
new CustomSerializer(
@@ -156,94 +135,11 @@ export default function initializeSerializerFactory() {
FormatTextEntity)
)
SerializerFactory.registerSerializer(
FunctionReferenceEntity,
new Serializer(FunctionReferenceEntity, Serializer.bracketsWrapped)
)
SerializerFactory.registerSerializer(
GuidEntity,
new ToStringSerializer(GuidEntity)
)
SerializerFactory.registerSerializer(
IdentifierEntity,
new ToStringSerializer(IdentifierEntity)
)
SerializerFactory.registerSerializer(
Integer64Entity,
new ToStringSerializer(Integer64Entity)
)
SerializerFactory.registerSerializer(
IntegerEntity,
new ToStringSerializer(IntegerEntity)
)
SerializerFactory.registerSerializer(
InvariantTextEntity,
new Serializer(InvariantTextEntity, (entity, v) => `${entity.getLookbehind()}(${v})`, ", ", false, "", () => "")
)
SerializerFactory.registerSerializer(
KeyBindingEntity,
new Serializer(KeyBindingEntity, Serializer.bracketsWrapped)
)
SerializerFactory.registerSerializer(
LinearColorEntity,
new Serializer(LinearColorEntity, Serializer.bracketsWrapped)
)
SerializerFactory.registerSerializer(
LocalizedTextEntity,
new Serializer(LocalizedTextEntity, (entity, v) => `${entity.getLookbehind()}(${v})`, ", ", false, "", () => "")
)
SerializerFactory.registerSerializer(
MacroGraphReferenceEntity,
new Serializer(MacroGraphReferenceEntity, Serializer.bracketsWrapped)
)
SerializerFactory.registeOrSerializer(
MirroredEntity,
new CustomSerializer(
(v, insideString) => SerializerFactory.getSerializer(v.getTargetType()).write(v.get(), insideString),
MirroredEntity
)
)
SerializerFactory.registerSerializer(
Number,
new ToStringSerializer(Number)
)
SerializerFactory.registerSerializer(
ObjectEntity,
new ObjectSerializer()
)
SerializerFactory.registerSerializer(
ObjectReferenceEntity,
new ToStringSerializer(ObjectReferenceEntity, false)
)
SerializerFactory.registerSerializer(
PathSymbolEntity,
new ToStringSerializer(PathSymbolEntity)
)
SerializerFactory.registerSerializer(
PinEntity,
new Serializer(PinEntity, (entity, v) => `${entity.getLookbehind()} (${v})`, ",", true)
)
SerializerFactory.registerSerializer(
PinReferenceEntity,
new Serializer(PinReferenceEntity, undefined, " ", false, "", () => "")
)
SerializerFactory.registerSerializer(
PinTypeEntity,
new Serializer(PinTypeEntity)

View File

@@ -1,16 +1,19 @@
import { expect, test } from "@playwright/test"
import Utility from "../js/Utility.js"
import ArrayEntity from "../js/entity/ArrayEntity.js"
import FormatTextEntity from "../js/entity/FormatTextEntity.js"
import GuidEntity from "../js/entity/GuidEntity.js"
import IntegerEntity from "../js/entity/IntegerEntity.js"
import KeyBindingEntity from "../js/entity/KeyBindingEntity.js"
import LinearColorEntity from "../js/entity/LinearColorEntity.js"
import NumberEntity from "../js/entity/NumberEntity.js"
import ObjectReferenceEntity from "../js/entity/ObjectReferenceEntity.js"
import PinEntity from "../js/entity/PinEntity.js"
import RotatorEntity from "../js/entity/RotatorEntity.js"
import SimpleSerializationRotatorEntity from "../js/entity/SimpleSerializationRotatorEntity.js"
import SimpleSerializationVector2DEntity from "../js/entity/SimpleSerializationVector2DEntity.js"
import SimpleSerializationVectorEntity from "../js/entity/SimpleSerializationVectorEntity.js"
import StringEntity from "../js/entity/StringEntity.js"
import SymbolEntity from "../js/entity/SymbolEntity.js"
import UnknownKeysEntity from "../js/entity/UnknownKeysEntity.js"
import Vector2DEntity from "../js/entity/Vector2DEntity.js"
@@ -23,30 +26,48 @@ test.beforeAll(() => initializeSerializerFactory())
test.describe.configure({ mode: "parallel" })
test("Array", () => {
const serializer = SerializerFactory.getSerializer(Array)
test("ArrayEntity", () => {
let grammar = ArrayEntity.grammar
expect(serializer.read("()")).toStrictEqual([])
expect(serializer.read("( )")).toStrictEqual([])
expect(serializer.read("(1, 2, 3, 4, 5, 6)")).toStrictEqual([1, 2, 3, 4, 5, 6])
expect(serializer.read(`(
expect(grammar.parse("()")).toEqual(new ArrayEntity([]))
expect(grammar.parse("( )")).toEqual(new ArrayEntity([]))
expect(grammar.parse("(1, 2, 3, 4, 5, 6)")).toEqual(new ArrayEntity([
new NumberEntity(1),
new NumberEntity(2),
new NumberEntity(3),
new NumberEntity(4),
new NumberEntity(5),
new NumberEntity(6),
]))
expect(ArrayEntity.of(NumberEntity).grammar.parse("(2,4,6,8)")).toEqual(new ArrayEntity([
new NumberEntity(2),
new NumberEntity(4),
new NumberEntity(6),
new NumberEntity(8),
]))
expect(ArrayEntity.of(IntegerEntity).grammar.parse("(-0, -1, -2)")).toEqual(new ArrayEntity([
new IntegerEntity(0),
new IntegerEntity(-1),
new IntegerEntity(-2),
]))
expect(() => ArrayEntity.of(IntegerEntity).grammar.parse("(-1, -2.1, -3)")).toThrowError()
expect(grammar.parse(`(
"alpha",
"beta",
123,
3BEF2168446CAA32D5B54289FAB2F0BA,
Some(a=1, b="2")
)`)).toStrictEqual([
"alpha",
"beta",
123,
)`)).toStrictEqual(new ArrayEntity([
new StringEntity("alpha"),
new StringEntity("beta"),
new NumberEntity(123),
new GuidEntity("3BEF2168446CAA32D5B54289FAB2F0BA"),
new UnknownKeysEntity({
lookbehind: "Some",
new (UnknownKeysEntity.withLookbehind("Some"))({
a: 1,
b: "2",
})
])
expect(serializer.read(`(
]))
expect(grammar.parse(`(
A(first = (9,8,7,6,5), second = 00000000000000000000000000000000),
B(key="hello"),
)`)).toStrictEqual([
@@ -62,9 +83,9 @@ test("Array", () => {
])
// Nested
expect(serializer.read("((1, 2), (3, 4))")).toStrictEqual([[1, 2], [3, 4]])
expect(serializer.read('(((1, 2), (3, 4)), 5)')).toStrictEqual([[[1, 2], [3, 4]], 5])
expect(serializer.read(`(
expect(grammar.parse("((1, 2), (3, 4))")).toStrictEqual([[1, 2], [3, 4]])
expect(grammar.parse('(((1, 2), (3, 4)), 5)')).toStrictEqual([[[1, 2], [3, 4]], 5])
expect(grammar.parse(`(
One(a = (1,(2,(3,(4)))), b = ()),
)`)).toStrictEqual([
new UnknownKeysEntity({

View File

@@ -1,25 +1,17 @@
import AttributeInfo from "../../js/entity/AttributeInfo.js"
import IEntity from "../../js/entity/IEntity.js"
import Union from "../../js/entity/Union.js"
import NumberEntity from "../../js/entity/NumberEntity.js"
import StringEntity from "../../js/entity/StringEntity.js"
import Grammar from "../../js/serialization/Grammar.js"
export default class EntityF extends IEntity {
static lookbehind = ["Foo", "Bar"]
static attributes = {
...super.attributes,
arg1: AttributeInfo.createType(Number),
arg2: AttributeInfo.createType(String),
lookbehind: new AttributeInfo({
...super.attributes.lookbehind,
default: new Union("Foo", "Bar"),
})
}
static grammar = this.createGrammar()
static createGrammar() {
return Grammar.createEntityGrammar(this, false)
arg1: NumberEntity,
arg2: StringEntity,
}
static grammar = Grammar.createEntityGrammar(this)
constructor(values = {}) {
super(values)

View File

@@ -96,6 +96,19 @@
* (value: T): typeof value.constructor,
* }} TypeGetter
*/
/**
* @template T
* @typedef {T extends [infer A extends EntityConstructor] ? InstanceType<A>
* : T extends [infer A extends EntityConstructor, ...infer B] ? InstanceType<A> | UnionFromArray<B>
* : never
* } UnionFromArray
*/
/**
* @template {EntityConstructor} T
* @typedef {T extends AlternativesEntityConstructor & { alternatives: infer R } ? UnionFromArray<R>
* : InstanceType<T>
* } ExtractType
*/
/**
* @typedef {typeof import("./js/Blueprint.js").default} BlueprintConstructor
* @typedef {typeof import("./js/element/LinkElement.js").default} LinkElementConstructor
@@ -103,6 +116,7 @@
* @typedef {typeof import("./js/element/PinElement.js").default} PinElementConstructor
* @typedef {typeof import("./js/element/WindowElement.js").default} WindowElementConstructor
* @typedef {typeof import("./js/entity/IEntity.js").default} EntityConstructor
* @typedef {typeof import("./js/entity/AlternativesEntity.js").default} AlternativesEntityConstructor
* @typedef {typeof import("./js/entity/ObjectEntity.js").default} ObjectEntityConstructor
*/
/**
@@ -207,20 +221,11 @@
* @typedef {import("lit").CSSResult} CSSResult
* @typedef {import("lit").PropertyValues} PropertyValues
* @typedef {import("lit").TemplateResult} TemplateResult
* @typedef {import("parsernostrum/src/parser/Parser.js").default} Parser
*/
/**
* @template {AttributeConstructor<Attribute>} T
* @typedef {import("./js/serialization/Serializer.js").default<T>} Serializer
*/
/**
* @template {Attribute} T
* @typedef {import("./js/entity/MirroredEntity.js").default<T>} MirroredEntity
*/
/**
* @template {Attribute} T
* @typedef {typeof import("./js/entity/MirroredEntity.js").default<T>} MirroredEntityConstructor
*/
/**
* @template T
* @typedef {{
@@ -228,3 +233,7 @@
* evaluate<R>(pageFunction: (node: T) => R, options?: { timeout?: number }): Promise<R>
* } & import("@playwright/test").Locator} Locator
*/
/**
* @template T
* @typedef {import("parsernostrum").ProducerParser<T>} Parser
*/