Skip to content

Commit

Permalink
fix a bug in the serializer throwing unhelpfully at a null (=unset/un…
Browse files Browse the repository at this point in the history
…resolved) reference
  • Loading branch information
dslmeinte committed Sep 16, 2024
1 parent 824f144 commit 90513a9
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 52 deletions.
2 changes: 2 additions & 0 deletions packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ The following is a list of links to potential starting points:
The `AccumulatingSimplisticHandler` class accumulates the problems reported, which can be accessed through its `allProblems` method.
The `AggregatingSimplisticHandler` class aggregates the problems reported (with count), which can be output using its `reportAllProblemsOnConsole` method, and accessed through its `allProblems` method.
* Pass dependent languages also _as languages_ from languages deserializer to regular deserializer, not just as referable data (which is only useful for the built-ins)
* Fix a bug in the serializer that caused an "unhelpful" exception on an unset or unresolved — i.e., "not-connected", represented by a `null` value — reference target .
Now, such reference targets are simply skipped.


### 0.6.8
Expand Down
21 changes: 14 additions & 7 deletions packages/core/src/serializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {ExtractionFacade} from "./facade.js"
import {currentSerializationFormatVersion, MetaPointer, SerializationChunk, SerializedNode} from "./serialization.js"
import {asIds} from "./functions.js"
import {Node} from "./types.js"
import {unresolved} from "./references.js"
import {DefaultPrimitiveTypeSerializer} from "./m3/builtins.js"
import {allFeaturesOf} from "./m3/functions.js"
import {
Expand All @@ -15,6 +16,7 @@ import {
} from "./m3/types.js"
import {asArray} from "./utils/array-helpers.js"


export interface PrimitiveTypeSerializer {
serializeValue(value: unknown, property: Property): string | undefined
}
Expand Down Expand Up @@ -94,15 +96,20 @@ export const serializeNodes = <NT extends Node>(
return
}
if (feature instanceof Reference) {
const targets = asArray(value)
// Note: value can be null === typeof unresolved, e.g. on an unset (or previously unresolved) single-valued reference
const targets = asArray(value) as (NT | typeof unresolved)[]
serializedNode.references.push({
reference: featureMetaPointer,
targets: (targets as NT[]).map((t) => ({
resolveInfo: extractionFacade.resolveInfoFor
? extractionFacade.resolveInfoFor(t)
: simpleNameDeducer(t),
reference: t.id
}))
targets: targets
.filter((tOrNull) => tOrNull !== null) // (skip "non-connected" targets)
.map((t) => t!)
.map((t) => ({
resolveInfo: extractionFacade.resolveInfoFor
? extractionFacade.resolveInfoFor(t)
: simpleNameDeducer(t),
reference: t.id
})
)
})
return
}
Expand Down
105 changes: 60 additions & 45 deletions packages/test/src/serializer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DefaultPrimitiveTypeSerializer,
Language,
SerializationChunk,
serializeLanguages,
serializeNodes
} from "@lionweb/core"
import {dateDatatype, libraryWithDatesLanguage} from "./languages/libraryWithDates.js"
Expand Down Expand Up @@ -39,10 +40,10 @@ describe("serialization", () => {

const expectedSerializationChunk: SerializationChunk = {
serializationFormatVersion: currentSerializationFormatVersion,
"languages": [
languages: [
{
"key": "libraryWithDates",
"version": "1"
key: "libraryWithDates",
version: "1"
}
],
nodes: [
Expand Down Expand Up @@ -73,11 +74,11 @@ describe("serialization", () => {
],
containments: [
{
"children": [],
"containment": {
"key": "books",
"language": "libraryWithDates",
"version": "1"
children: [],
containment: {
key: "books",
language: "libraryWithDates",
version: "1"
}
}
],
Expand Down Expand Up @@ -105,68 +106,82 @@ describe("serialization", () => {
annotatedNode.annotations.push(annotation)

const expectedSerializationChunk = {
"serializationFormatVersion": "2023.1",
"languages": [
serializationFormatVersion: "2023.1",
languages: [
{
"key": "test-language",
"version": "0"
key: "test-language",
version: "0"
},
{
"key": "LionCore-builtins",
"version": "2023.1"
key: "LionCore-builtins",
version: "2023.1"
}
],
"nodes": [
nodes: [
{
"id": "1",
"classifier": {
"language": "test-language",
"version": "0",
"key": "Annotated"
id: "1",
classifier: {
language: "test-language",
version: "0",
key: "Annotated"
},
"properties": [
properties: [
{
"property": {
"language": "LionCore-builtins",
"version": "2023.1",
"key": "LionCore-builtins-INamed-name"
property: {
language: "LionCore-builtins",
version: "2023.1",
key: "LionCore-builtins-INamed-name"
},
"value": "my annotated node"
value: "my annotated node"
}
],
"containments": [],
"references": [],
"annotations": [
containments: [],
references: [],
annotations: [
"0"
],
"parent": null
parent: null
},
{
"id": "0",
"classifier": {
"language": "test-language",
"version": "0",
"key": "Annotation"
id: "0",
classifier: {
language: "test-language",
version: "0",
key: "Annotation"
},
"properties": [
properties: [
{
"property": {
"language": "LionCore-builtins",
"version": "2023.1",
"key": "LionCore-builtins-INamed-name"
property: {
language: "LionCore-builtins",
version: "2023.1",
key: "LionCore-builtins-INamed-name"
},
"value": "my annotation node"
value: "my annotation node"
}
],
"containments": [],
"references": [],
"annotations": [],
"parent": "1"
containments: [],
references: [],
annotations: [],
parent: "1"
}
]
}
expect(serializeNodes([annotatedNode], new SimpleNodeReader([language]))).to.eql(expectedSerializationChunk)
})

it(`doesn't fail on "unconnected" (i.e., unset or previously unresolved) null reference target values`, () => {
const language = new Language("test language", "0", "test-language", "test-language")
const annotation = new Annotation(language, "Annotation", "Annotation", "Annotation")
// don't set annotation.annotates!
language.havingEntities(annotation)

const serializationChunk = serializeLanguages(language) // should not fail
const annotationSerNode = serializationChunk.nodes.find((node) => node.id === "Annotation")
expect(annotationSerNode).to.not.be.null
const referenceSer = annotationSerNode?.references.find((serRef) => serRef.reference.key === "Annotation-annotates")
expect(referenceSer).to.not.be.undefined
expect(referenceSer!.targets).to.eql([])
})

})

0 comments on commit 90513a9

Please sign in to comment.