/
compose-collection.ts
93 lines (87 loc) · 2.71 KB
/
compose-collection.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { Type } from '../constants.js'
import type { Document } from '../doc/Document.js'
import { isNode, ParsedNode } from '../nodes/Node.js'
import { Scalar } from '../nodes/Scalar.js'
import type { YAMLMap } from '../nodes/YAMLMap.js'
import type { YAMLSeq } from '../nodes/YAMLSeq.js'
import type {
BlockMap,
BlockSequence,
FlowCollection
} from '../parse/tokens.js'
import { CollectionTag } from '../tags/types.js'
import type { ComposeNode } from './compose-node.js'
import { resolveBlockMap } from './resolve-block-map.js'
import { resolveBlockSeq } from './resolve-block-seq.js'
import { resolveFlowCollection } from './resolve-flow-collection.js'
export function composeCollection(
CN: ComposeNode,
doc: Document.Parsed,
token: BlockMap | BlockSequence | FlowCollection,
anchor: string | null,
tagName: string | null,
onError: (offset: number, message: string, warning?: boolean) => void
) {
let coll: YAMLMap.Parsed | YAMLSeq.Parsed
switch (token.type) {
case 'block-map': {
coll = resolveBlockMap(CN, doc, token, anchor, onError)
break
}
case 'block-seq': {
coll = resolveBlockSeq(CN, doc, token, anchor, onError)
break
}
case 'flow-collection': {
coll = resolveFlowCollection(CN, doc, token, anchor, onError)
break
}
}
if (!tagName) return coll
// Cast needed due to: https://github.com/Microsoft/TypeScript/issues/3841
const Coll = coll.constructor as typeof YAMLMap | typeof YAMLSeq
if (tagName === '!' || tagName === Coll.tagName) {
coll.tag = Coll.tagName
return coll
}
let expType: 'map' | 'seq' // | null = null
switch (coll.type) {
case Type.FLOW_MAP:
case Type.MAP:
expType = 'map'
break
case Type.FLOW_SEQ:
case Type.SEQ:
expType = 'seq'
break
default:
onError(coll.range[0], `Unexpected collection type: ${coll.type}`)
coll.tag = tagName
return coll
}
let tag = doc.schema.tags.find(
t => t.collection === expType && t.tag === tagName
) as CollectionTag | undefined
if (!tag) {
const kt = doc.schema.knownTags[tagName]
if (kt && kt.collection === expType) {
doc.schema.tags.push(Object.assign({}, kt, { default: false }))
tag = kt
} else {
onError(coll.range[0], `Unresolved tag: ${tagName}`, true)
coll.tag = tagName
return coll
}
}
const res = tag.resolve(coll, msg => onError(coll.range[0], msg), doc.options)
const node = isNode(res)
? (res as ParsedNode)
: (new Scalar(res) as Scalar.Parsed)
node.range = coll.range
node.tag = tagName
if (tag?.format) (node as Scalar).format = tag.format
if (anchor && node !== coll) {
// FIXME: handle anchor for non-failsafe collections
}
return node
}