in language-service/src/parser/yamlParser.ts [200:248]
function addItemsToArrayNode(node: ArrayASTNode, items: Yaml.YAMLNode[]): void {
let count = 0;
for (const item of items) {
// TODO: What the heck is this check
if (item === null && count === items.length - 1) {
break;
}
let itemNode: ASTNode;
if (item === null) {
// Be aware of https://github.com/nodeca/js-yaml/issues/321
// Cannot simply work around it here because we need to know if we are in Flow or Block
itemNode = new NullASTNode(node.parent, null, node.end, node.end);
} else {
if (item.kind === Yaml.Kind.MAP &&
item.mappings[0].key.value.startsWith("${{") &&
item.mappings[0].key.value.endsWith("}}")) {
const value = item.mappings[0].value;
if (value === null) {
continue;
}
if (value.kind === Yaml.Kind.SEQ) {
// e.g. conditionally adding steps to a job.
addItemsToArrayNode(node, item.mappings[0].value.items);
count++;
continue;
} else if (value.kind === Yaml.Kind.MAP) {
// e.g. looping through a stepList parameter and checking each value.
// NOTE: We don't have a great story for this as we can't validate
// the resulting ${{ pair.key }}: ${{ pair.value }} against the schema,
// so we currently just create an empty object with no properties.
// We might need to revisit this if we start providing LSP capabilities
// for expressions.
itemNode = recursivelyBuildAst(node, value);
} else {
throw new Error(`Unexpected kind ${value.kind}`);
}
} else {
itemNode = recursivelyBuildAst(node, item);
}
}
itemNode.location = node.items.length;
node.addItem(itemNode);
count++;
}
}