@lionweb/utilities 0.7.0-beta.18 → 0.7.0-beta.19
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 +1 -0
- package/package.json +5 -5
- package/src/hashing.ts +148 -0
- package/src/index.ts +5 -0
- package/src/m1/reference-utils.ts +2 -0
- package/src/m3/dependencies.ts +62 -0
- package/src/m3/diagrams/Mermaid-generator.ts +129 -0
- package/src/m3/diagrams/PlantUML-generator.ts +147 -0
- package/src/m3/index.ts +6 -0
- package/src/m3/infer-languages.ts +147 -0
- package/src/m3/textualizer.ts +95 -0
- package/src/m3/ts-generation/common.ts +48 -0
- package/src/m3/ts-generation/ts-types-generator.ts +226 -0
- package/src/m3/ts-generation/type-def.ts +40 -0
- package/src/serialization/annotation-remover.ts +46 -0
- package/src/serialization/chunk.ts +105 -0
- package/src/serialization/index.ts +6 -0
- package/src/serialization/measurer.ts +115 -0
- package/src/serialization/metric-types.ts +43 -0
- package/src/serialization/ordering.ts +73 -0
- package/src/serialization/sorting.ts +33 -0
- package/src/serialization/textualizer.ts +93 -0
- package/src/utils/json.ts +8 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { LionWebKey } from "@lionweb/json"
|
|
2
|
+
|
|
3
|
+
type OptionallyNamed = {
|
|
4
|
+
name?: string // == name when it can be looked up
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
type LanguagePointer = {
|
|
8
|
+
key: LionWebKey
|
|
9
|
+
version: string
|
|
10
|
+
} & OptionallyNamed
|
|
11
|
+
|
|
12
|
+
/* abstract */ type ClassifierMetric = {
|
|
13
|
+
language: LanguagePointer
|
|
14
|
+
key: LionWebKey // key of classifier
|
|
15
|
+
} & OptionallyNamed
|
|
16
|
+
|
|
17
|
+
type ClassifierMetaTypes = "annotation" | "concept" | "interface"
|
|
18
|
+
|
|
19
|
+
type ClassifierInstantiationMetric = {
|
|
20
|
+
metaType?: ClassifierMetaTypes
|
|
21
|
+
instantiations: number
|
|
22
|
+
} & ClassifierMetric
|
|
23
|
+
|
|
24
|
+
type LanguageMetric = {
|
|
25
|
+
instantiations: number
|
|
26
|
+
} & LanguagePointer
|
|
27
|
+
|
|
28
|
+
// TODO order?
|
|
29
|
+
type Metrics = {
|
|
30
|
+
languagesWithInstantiations: LanguageMetric[]
|
|
31
|
+
instantiatedClassifiers: ClassifierInstantiationMetric[]
|
|
32
|
+
uninstantiatedInstantiableClassifiers: ClassifierMetric[]
|
|
33
|
+
languagesWithoutInstantiations: LanguagePointer[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
export type {
|
|
38
|
+
ClassifierInstantiationMetric,
|
|
39
|
+
ClassifierMetaTypes,
|
|
40
|
+
LanguagePointer,
|
|
41
|
+
Metrics
|
|
42
|
+
}
|
|
43
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LionWebJsonChunk,
|
|
3
|
+
LionWebJsonContainment,
|
|
4
|
+
LionWebJsonMetaPointer,
|
|
5
|
+
LionWebJsonNode,
|
|
6
|
+
LionWebJsonProperty,
|
|
7
|
+
LionWebJsonReference,
|
|
8
|
+
LionWebJsonReferenceTarget,
|
|
9
|
+
LionWebJsonUsedLanguage
|
|
10
|
+
} from "@lionweb/json"
|
|
11
|
+
|
|
12
|
+
const orderedMetaPointer = ({ language, version, key }: LionWebJsonMetaPointer): LionWebJsonMetaPointer => ({
|
|
13
|
+
language,
|
|
14
|
+
version,
|
|
15
|
+
key
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const orderedSerializedLanguageReference = ({ key, version }: LionWebJsonUsedLanguage): LionWebJsonUsedLanguage => ({
|
|
19
|
+
key,
|
|
20
|
+
version
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const orderedSerializedReferenceTarget = ({ reference, resolveInfo }: LionWebJsonReferenceTarget): LionWebJsonReferenceTarget => ({
|
|
24
|
+
resolveInfo,
|
|
25
|
+
reference
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const orderedSerializedProperty = ({ property, value }: LionWebJsonProperty): LionWebJsonProperty => ({
|
|
29
|
+
property: orderedMetaPointer(property),
|
|
30
|
+
value
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const orderedSerializedContainment = ({ containment, children }: LionWebJsonContainment): LionWebJsonContainment => ({
|
|
34
|
+
containment: orderedMetaPointer(containment),
|
|
35
|
+
children // TODO ensure [] if empty
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const orderedSerializedReference = ({ reference, targets }: LionWebJsonReference): LionWebJsonReference => ({
|
|
39
|
+
reference: orderedMetaPointer(reference),
|
|
40
|
+
targets: targets.map(orderedSerializedReferenceTarget) // TODO ensure [] if empty
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const orderedSerializedNode = ({
|
|
44
|
+
id,
|
|
45
|
+
classifier,
|
|
46
|
+
properties,
|
|
47
|
+
containments,
|
|
48
|
+
references,
|
|
49
|
+
annotations,
|
|
50
|
+
parent
|
|
51
|
+
}: LionWebJsonNode): LionWebJsonNode => ({
|
|
52
|
+
id,
|
|
53
|
+
classifier: orderedMetaPointer(classifier),
|
|
54
|
+
properties: properties.map(orderedSerializedProperty),
|
|
55
|
+
containments: containments.map(orderedSerializedContainment),
|
|
56
|
+
references: references.map(orderedSerializedReference),
|
|
57
|
+
annotations, // TODO ensure [] if empty
|
|
58
|
+
parent
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const orderedSerializationChunk = ({ serializationFormatVersion, languages, nodes }: LionWebJsonChunk): LionWebJsonChunk => ({
|
|
62
|
+
serializationFormatVersion,
|
|
63
|
+
languages: languages.map(orderedSerializedLanguageReference),
|
|
64
|
+
nodes: nodes.map(orderedSerializedNode)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
orderedMetaPointer,
|
|
69
|
+
orderedSerializationChunk,
|
|
70
|
+
orderedSerializedLanguageReference,
|
|
71
|
+
orderedSerializedProperty,
|
|
72
|
+
orderedSerializedReferenceTarget
|
|
73
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LionWebJsonChunk } from "@lionweb/json"
|
|
2
|
+
import { sortByStringKey } from "@lionweb/ts-utils"
|
|
3
|
+
import { orderedMetaPointer, orderedSerializedLanguageReference, orderedSerializedProperty, orderedSerializedReferenceTarget } from "./ordering.js"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @return A sorted version of a {@link SerializedModel JSON serialization}, which should make it easier to inspect.
|
|
8
|
+
* Note that the sorted version destroy the order of links, which might effectively alter semantics.
|
|
9
|
+
*/
|
|
10
|
+
export const sortedSerializationChunk = ({serializationFormatVersion, languages, nodes}: LionWebJsonChunk): LionWebJsonChunk =>
|
|
11
|
+
({
|
|
12
|
+
serializationFormatVersion,
|
|
13
|
+
languages: sortByStringKey(languages, ({key}) => key).map(orderedSerializedLanguageReference),
|
|
14
|
+
nodes: sortByStringKey(nodes, ({id}) => id)
|
|
15
|
+
.map((node) => ({
|
|
16
|
+
id: node.id,
|
|
17
|
+
classifier: orderedMetaPointer(node.classifier),
|
|
18
|
+
properties: sortByStringKey(node.properties, ({property}) => property.key).map(orderedSerializedProperty),
|
|
19
|
+
containments: sortByStringKey(node.containments, ({containment}) => containment.key)
|
|
20
|
+
.map(({containment, children}) => ({
|
|
21
|
+
containment: orderedMetaPointer(containment),
|
|
22
|
+
children: children.sort()
|
|
23
|
+
})),
|
|
24
|
+
references: sortByStringKey(node.references, ({reference}) => reference.key)
|
|
25
|
+
.map(({reference, targets}) => ({
|
|
26
|
+
reference: orderedMetaPointer(reference),
|
|
27
|
+
targets: sortByStringKey(targets, ({reference}) => reference).map(orderedSerializedReferenceTarget)
|
|
28
|
+
})),
|
|
29
|
+
annotations: node.annotations.sort(),
|
|
30
|
+
parent: node.parent
|
|
31
|
+
}))
|
|
32
|
+
})
|
|
33
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { Enumeration, Language, MemoisingSymbolTable, Property } from "@lionweb/core"
|
|
2
|
+
import {
|
|
3
|
+
LionWebId,
|
|
4
|
+
LionWebJsonChunk,
|
|
5
|
+
LionWebJsonContainment,
|
|
6
|
+
LionWebJsonMetaPointer,
|
|
7
|
+
LionWebJsonNode,
|
|
8
|
+
LionWebJsonProperty,
|
|
9
|
+
LionWebJsonReference,
|
|
10
|
+
LionWebJsonReferenceTarget
|
|
11
|
+
} from "@lionweb/json"
|
|
12
|
+
import { byIdMap } from "@lionweb/ts-utils"
|
|
13
|
+
import { asString, indentWith, Template } from "littoral-templates"
|
|
14
|
+
|
|
15
|
+
const indent = indentWith(" ")(1)
|
|
16
|
+
|
|
17
|
+
const prependWith = (template: Template, prefix: string): Template => prefix + asString(template)
|
|
18
|
+
|
|
19
|
+
export const genericAsTreeText = ({ nodes }: LionWebJsonChunk, languages: Language[] = []) => {
|
|
20
|
+
const nodesById: { [id: LionWebId]: LionWebJsonNode } = byIdMap(nodes)
|
|
21
|
+
const symbolTable = new MemoisingSymbolTable(languages)
|
|
22
|
+
|
|
23
|
+
const nameOrKey = (classifier: LionWebJsonMetaPointer, feature: LionWebJsonMetaPointer): string =>
|
|
24
|
+
symbolTable.featureMatching(classifier, feature)?.name ?? `[${feature.key}]`
|
|
25
|
+
|
|
26
|
+
const propertyAsText = (classifier: LionWebJsonMetaPointer, { property: propertyMetaPointer, value }: LionWebJsonProperty) => {
|
|
27
|
+
const property = symbolTable.featureMatching(classifier, propertyMetaPointer)
|
|
28
|
+
const identification = nameOrKey(classifier, propertyMetaPointer)
|
|
29
|
+
const displayValue =
|
|
30
|
+
property instanceof Property
|
|
31
|
+
? property.type instanceof Enumeration
|
|
32
|
+
? (property.type.literals.find(literal => literal.key === value)?.name ?? value)
|
|
33
|
+
: (() => {
|
|
34
|
+
switch (property?.type?.name) {
|
|
35
|
+
case "String":
|
|
36
|
+
return `'${value}'`
|
|
37
|
+
default:
|
|
38
|
+
return value
|
|
39
|
+
}
|
|
40
|
+
})()
|
|
41
|
+
: value
|
|
42
|
+
return `${identification} = ${displayValue}`
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const referenceTargetAsText = ({ reference: referenceId, resolveInfo }: LionWebJsonReferenceTarget) =>
|
|
46
|
+
`${referenceId}${resolveInfo === undefined ? `` : ` (${resolveInfo})`}`
|
|
47
|
+
|
|
48
|
+
const referenceAsText = (classifier: LionWebJsonMetaPointer, { reference, targets }: LionWebJsonReference) =>
|
|
49
|
+
`${nameOrKey(classifier, reference)} -> ${targets.length === 0 ? `<none>` : targets.map(referenceTargetAsText).join(", ")}`
|
|
50
|
+
|
|
51
|
+
const containmentAsText = (classifier: LionWebJsonMetaPointer, { containment, children }: LionWebJsonContainment) => [
|
|
52
|
+
`${nameOrKey(classifier, containment)}:${children.length === 0 ? ` <none>` : ``}`,
|
|
53
|
+
indent(
|
|
54
|
+
children.map(childId =>
|
|
55
|
+
childId in nodesById ? asText(nodesById[childId]) : `<child with id=${childId} not present in this chunk>`
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
const annotationAsText = (annotationId: LionWebId) =>
|
|
61
|
+
annotationId in nodesById
|
|
62
|
+
? prependWith(asText(nodesById[annotationId]), "@ ")
|
|
63
|
+
: `<annotation with id=${annotationId} not present in this chunk>`
|
|
64
|
+
|
|
65
|
+
const curry1 =
|
|
66
|
+
<T1, T2, R>(func: (t1: T1, t2: T2) => R, t1: T1): ((t2: T2) => R) =>
|
|
67
|
+
(t2: T2) =>
|
|
68
|
+
func(t1, t2)
|
|
69
|
+
|
|
70
|
+
const asText = ({
|
|
71
|
+
id,
|
|
72
|
+
classifier: classifierMetaPointer,
|
|
73
|
+
properties,
|
|
74
|
+
containments,
|
|
75
|
+
references,
|
|
76
|
+
annotations
|
|
77
|
+
}: LionWebJsonNode): Template => [
|
|
78
|
+
`${symbolTable.entityMatching(classifierMetaPointer)?.name ?? `[${classifierMetaPointer.key}]`} (id: ${id}) {`,
|
|
79
|
+
indent([
|
|
80
|
+
properties.map(curry1(propertyAsText, classifierMetaPointer)),
|
|
81
|
+
references.map(curry1(referenceAsText, classifierMetaPointer)),
|
|
82
|
+
containments.map(curry1(containmentAsText, classifierMetaPointer)),
|
|
83
|
+
annotations.map(annotationAsText)
|
|
84
|
+
]),
|
|
85
|
+
`}`
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
return asString(
|
|
89
|
+
nodes
|
|
90
|
+
.filter(node => node.parent === null) // root nodes
|
|
91
|
+
.map(asText)
|
|
92
|
+
)
|
|
93
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { asPrettyJsonString } from "@lionweb/ts-utils"
|
|
2
|
+
import { readFileSync, writeFileSync } from "fs"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const writeJsonAsFile = (path: string, json: unknown) => writeFileSync(path, asPrettyJsonString(json))
|
|
6
|
+
|
|
7
|
+
export const readFileAsJson = (path: string): unknown => JSON.parse(readFileSync(path).toString())
|
|
8
|
+
|