217 lines
7.3 KiB
JavaScript
217 lines
7.3 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.KeysResolver = void 0;
|
|
const internal_utils_1 = require("../internal-utils");
|
|
class KeysResolver {
|
|
constructor(ctx) {
|
|
this.rootKeys = new Map();
|
|
this.tables = [];
|
|
this.ctx = ctx;
|
|
}
|
|
applyResolveKeyForTable(node) {
|
|
let keys = this.rootKeys;
|
|
const peekKeyIndex = node.key.keys.length - 1;
|
|
for (let index = 0; index < peekKeyIndex; index++) {
|
|
const keyNode = node.key.keys[index];
|
|
const keyName = (0, internal_utils_1.toKeyName)(keyNode);
|
|
node.resolvedKey.push(keyName);
|
|
let keyStore = keys.get(keyName);
|
|
if (!keyStore) {
|
|
keyStore = { node: keyNode, keys: new Map() };
|
|
keys.set(keyName, keyStore);
|
|
}
|
|
else if (keyStore.table === "array") {
|
|
const peekIndex = keyStore.peekIndex;
|
|
node.resolvedKey.push(peekIndex);
|
|
keyStore = keyStore.keys.get(peekIndex);
|
|
}
|
|
keys = keyStore.keys;
|
|
}
|
|
const lastKeyNode = node.key.keys[peekKeyIndex];
|
|
const lastKeyName = (0, internal_utils_1.toKeyName)(lastKeyNode);
|
|
node.resolvedKey.push(lastKeyName);
|
|
const lastKeyStore = keys.get(lastKeyName);
|
|
if (!lastKeyStore) {
|
|
if (node.kind === "array") {
|
|
node.resolvedKey.push(0);
|
|
const newKeyStore = {
|
|
node: lastKeyNode,
|
|
keys: new Map(),
|
|
};
|
|
keys.set(lastKeyName, {
|
|
table: node.kind,
|
|
node: lastKeyNode,
|
|
keys: new Map([[0, newKeyStore]]),
|
|
peekIndex: 0,
|
|
});
|
|
this.tables.push({ node, keys: newKeyStore.keys });
|
|
}
|
|
else {
|
|
const newKeyStore = {
|
|
table: node.kind,
|
|
node: lastKeyNode,
|
|
keys: new Map(),
|
|
};
|
|
keys.set(lastKeyName, newKeyStore);
|
|
this.tables.push({ node, keys: newKeyStore.keys });
|
|
}
|
|
}
|
|
else if (!lastKeyStore.table) {
|
|
if (node.kind === "array") {
|
|
// e.g.
|
|
// [key.foo]
|
|
// [[key]]
|
|
this.ctx.reportParseError("dupe-keys", lastKeyNode);
|
|
}
|
|
else {
|
|
const transformKey = {
|
|
table: node.kind,
|
|
node: lastKeyNode,
|
|
keys: lastKeyStore.keys,
|
|
};
|
|
keys.set(lastKeyName, transformKey);
|
|
this.tables.push({ node, keys: transformKey.keys });
|
|
}
|
|
}
|
|
else if (lastKeyStore.table === "array") {
|
|
if (node.kind === "array") {
|
|
const newKeyStore = {
|
|
node: lastKeyNode,
|
|
keys: new Map(),
|
|
};
|
|
const newIndex = lastKeyStore.peekIndex + 1;
|
|
node.resolvedKey.push(newIndex);
|
|
lastKeyStore.keys.set(newIndex, newKeyStore);
|
|
lastKeyStore.peekIndex = newIndex;
|
|
this.tables.push({ node, keys: newKeyStore.keys });
|
|
}
|
|
else {
|
|
// e.g.
|
|
// [[key]]
|
|
// [key]
|
|
this.ctx.reportParseError("dupe-keys", lastKeyNode);
|
|
}
|
|
}
|
|
else {
|
|
// e.g.
|
|
// [key]
|
|
// [key]
|
|
this.ctx.reportParseError("dupe-keys", lastKeyNode);
|
|
}
|
|
}
|
|
verifyDuplicateKeys(node) {
|
|
for (const body of node.body) {
|
|
if (body.type === "TOMLKeyValue") {
|
|
verifyDuplicateKeysForKeyValue(this.ctx, this.rootKeys, body);
|
|
}
|
|
}
|
|
for (const { node: tableNode, keys } of this.tables) {
|
|
for (const body of tableNode.body) {
|
|
verifyDuplicateKeysForKeyValue(this.ctx, keys, body);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports.KeysResolver = KeysResolver;
|
|
/**
|
|
* Verify duplicate keys from TOMLKeyValue
|
|
*/
|
|
function verifyDuplicateKeysForKeyValue(ctx, defineKeys, node) {
|
|
let keys = defineKeys;
|
|
const lastKey = (0, internal_utils_1.last)(node.key.keys);
|
|
for (const keyNode of node.key.keys) {
|
|
const key = (0, internal_utils_1.toKeyName)(keyNode);
|
|
let defineKey = keys.get(key);
|
|
if (defineKey) {
|
|
if (defineKey.value === 0 /* ValueKind.VALUE */) {
|
|
// e.g.
|
|
// key = 42
|
|
// key.foo = 42
|
|
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
|
|
}
|
|
else if (lastKey === keyNode) {
|
|
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
|
|
}
|
|
else if (defineKey.table) {
|
|
// e.g.
|
|
// key = 42
|
|
// [key]
|
|
// ---
|
|
// [key.foo]
|
|
// [key]
|
|
// foo.bar = 42
|
|
ctx.reportParseError("dupe-keys", getAfterNode(keyNode, defineKey.node));
|
|
}
|
|
defineKey.value = 1 /* ValueKind.INTERMEDIATE */;
|
|
}
|
|
else {
|
|
if (lastKey === keyNode) {
|
|
const keyStore = {
|
|
value: 0 /* ValueKind.VALUE */,
|
|
node: keyNode,
|
|
keys: new Map(),
|
|
};
|
|
defineKey = keyStore;
|
|
}
|
|
else {
|
|
const keyStore = {
|
|
value: 1 /* ValueKind.INTERMEDIATE */,
|
|
node: keyNode,
|
|
keys: new Map(),
|
|
};
|
|
defineKey = keyStore;
|
|
}
|
|
keys.set(key, defineKey);
|
|
}
|
|
keys = defineKey.keys;
|
|
}
|
|
if (node.value.type === "TOMLInlineTable") {
|
|
verifyDuplicateKeysForInlineTable(ctx, keys, node.value);
|
|
}
|
|
else if (node.value.type === "TOMLArray") {
|
|
verifyDuplicateKeysForArray(ctx, keys, node.value);
|
|
}
|
|
}
|
|
/**
|
|
* Verify duplicate keys from TOMLInlineTable
|
|
*/
|
|
function verifyDuplicateKeysForInlineTable(ctx, defineKeys, node) {
|
|
for (const body of node.body) {
|
|
verifyDuplicateKeysForKeyValue(ctx, defineKeys, body);
|
|
}
|
|
}
|
|
/**
|
|
* Verify duplicate keys from TOMLArray
|
|
*/
|
|
function verifyDuplicateKeysForArray(ctx, defineKeys, node) {
|
|
const keys = defineKeys;
|
|
for (let index = 0; index < node.elements.length; index++) {
|
|
const element = node.elements[index];
|
|
let defineKey = keys.get(index);
|
|
if (defineKey) {
|
|
// Probably not possible.
|
|
ctx.reportParseError("dupe-keys", getAfterNode(element, defineKey.node));
|
|
}
|
|
else {
|
|
defineKey = {
|
|
value: 0 /* ValueKind.VALUE */,
|
|
node: element,
|
|
keys: new Map(),
|
|
};
|
|
defineKeys.set(index, defineKey);
|
|
if (element.type === "TOMLInlineTable") {
|
|
verifyDuplicateKeysForInlineTable(ctx, defineKey.keys, element);
|
|
}
|
|
else if (element.type === "TOMLArray") {
|
|
verifyDuplicateKeysForArray(ctx, defineKey.keys, element);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
* Get the after node
|
|
*/
|
|
function getAfterNode(a, b) {
|
|
return a.range[0] <= b.range[0] ? b : a;
|
|
}
|