cspell
Version:
A Spelling Checker for Code!
127 lines • 3.52 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
const compare = Intl.Collator().compare;
export class ShallowObjectCollection {
tree = {};
get(v) {
if (typeof v !== 'object' || v === null) {
return v;
}
const keys = Object.entries(v)
.filter((entry) => entry[1] !== undefined)
.sort((a, b) => compare(a[0], b[0]));
let t = this.tree;
for (const [key, obj] of keys) {
if (!t.c) {
t.c = new Map();
}
const c0 = t.c.get(key);
const cc = c0 || new Map();
if (!c0) {
t.c.set(key, cc);
}
const c1 = cc.get(obj);
const ccc = c1 || {};
if (!c1) {
cc.set(obj, ccc);
}
t = ccc;
}
if (t.v)
return t.v;
t.v = v;
return v;
}
}
export class Collection {
col = { contains: new Map() };
/**
* Add a plain object to the collection.
* The actual object used is returned.
* By adding the object to the collection, it is now owned by the collection.
* Do not add class objects.
* @param v any object or primitive
* @returns v or the matching object.
*/
add(v) {
return addToCollection(this.col, v);
}
}
// const objectLike: TypeMask = {
// array: true,
// object: true,
// };
function addToCollection(root, v) {
const known = root.contains;
function addValToCol(c, v) {
const t = toValueType(v);
const val = c.v || Object.create(null);
const r = val[t] ?? v;
val[t] = r;
c.v = val;
return val[t];
}
function walk(col, path) {
path = path.filter((entry) => entry[1] !== undefined).sort((a, b) => compare(a[0], b[0]));
for (const [k, v] of path) {
const c = col.c || Object.create(null);
col.c = c;
const m = c[k] || new Map();
c[k] = m;
const has = m.get(v);
col = has || Object.create(null);
if (!has) {
m.set(v, col);
}
}
return col;
}
function normalizeObjectEntries(entries) {
for (const entry of entries) {
entry[1] = add(entry[1]);
}
return entries;
}
function normalizeToPath(v) {
if (typeof v !== 'object' || !v) {
return [['', v]];
}
const entries = normalizeObjectEntries(Object.entries(v));
const obj = v;
if (!Object.isFrozen(v)) {
for (const [k, v] of entries) {
obj[k] = v;
}
Object.freeze(obj);
}
return entries;
}
function add(v) {
const isObjectLike = typeof v === 'object' && !!v;
if (isObjectLike) {
const cached = known.get(v);
if (cached !== undefined) {
return cached;
}
known.set(v, v);
}
const path = normalizeToPath(v);
const c = walk(root, path);
const r = addValToCol(c, v);
if (isObjectLike) {
known.set(v, r);
}
return r;
}
return add(v);
}
function toValueType(v) {
const t = typeof v;
if (t !== 'object')
return t;
if (Array.isArray(v))
return 'array';
if (v === null)
return 'null';
return t;
}
//# sourceMappingURL=ObjectCollection.js.map