Files
routie/frontend/node_modules/@ota-meshi/ast-token-store/lib/index.mjs
T

465 lines
15 KiB
JavaScript

//#region rolldown:runtime
var __defProp = Object.defineProperty;
var __exportAll = (all, symbols) => {
let target = {};
for (var name$2 in all) {
__defProp(target, name$2, {
get: all[name$2],
enumerable: true
});
}
if (symbols) {
__defProp(target, Symbol.toStringTag, { value: "Module" });
}
return target;
};
//#endregion
//#region src/token-store/token-store.ts
/**
* Binary search for the index of the first token that is after the given location.
*/
function search(tokens, location) {
let minIndex = 0;
let maxIndex = tokens.length - 1;
while (minIndex <= maxIndex) {
const index = Math.floor((minIndex + maxIndex) / 2);
const tokenStartLocation = tokens[index].range[0];
if (tokenStartLocation < location) minIndex = index + 1;
else if (tokenStartLocation > location) maxIndex = index - 1;
else return index;
}
return minIndex;
}
/**
* Get the index of the first token that is after the given location.
*/
function getFirstIndex(tokens, indexMap, startLoc) {
let index = indexMap.get(startLoc);
if (index == null) index = search(tokens, startLoc);
while (index < tokens.length && tokens[index].range[1] <= tokens[index].range[0]) index++;
return index;
}
/**
* Get the index of the last token that is before the given location.
*/
function getLastIndex(tokens, indexMap, endLoc) {
let index = indexMap.get(endLoc);
if (index != null) index--;
else index = search(tokens, endLoc) - 1;
while (index >= 0 && tokens[index].range[1] <= tokens[index].range[0]) index--;
return index;
}
/**
* Normalizes the options for cursor methods.
*/
function normalizeSkipOptions(options, ctx) {
if (typeof options === "number") return {
filter: ctx.isNotComment,
skip: options
};
if (typeof options === "function") return {
filter: (n) => {
if (ctx.isComment(n)) return false;
return options(n);
},
skip: 0
};
let filter;
if (options?.includeComments) filter = options?.filter ?? (() => true);
else if (options?.filter) {
const baseFilter = options?.filter;
filter = (token) => {
if (ctx.isComment(token)) return false;
return baseFilter(token);
};
} else filter = ctx.isNotComment;
return {
filter,
skip: options?.skip ?? 0
};
}
/**
* Normalizes the options for cursor methods with count.
*/
function normalizeCountOptions(options, ctx) {
if (typeof options === "number") return {
filter: ctx.isNotComment,
count: options
};
if (typeof options === "function") return {
filter: (n) => {
if (ctx.isComment(n)) return false;
return options(n);
},
count: 0
};
let filter;
if (options?.includeComments) filter = options?.filter ?? (() => true);
else if (options?.filter) {
const baseFilter = options?.filter;
filter = (token) => {
if (ctx.isComment(token)) return false;
return baseFilter(token);
};
} else filter = ctx.isNotComment;
return {
filter,
count: options?.count ?? 0
};
}
const PRIVATE = Symbol("private");
var TokenStore = class {
[PRIVATE];
constructor(params) {
const allTokens = [...params.tokens].sort((a, b) => a.range[0] - b.range[0]);
const tokenStartToIndex = /* @__PURE__ */ new Map();
for (let i = 0; i < allTokens.length; i++) {
const token = allTokens[i];
if (token.range[0] < token.range[1]) tokenStartToIndex.set(token.range[0], i);
}
this[PRIVATE] = {
allTokens,
tokenStartToIndex,
ctx: {
isComment: params.isComment,
isNotComment: (token) => !params.isComment(token)
},
cacheAllComments: null
};
}
/**
* Gets all tokens, including comments.
*/
getAllTokens() {
return this[PRIVATE].allTokens;
}
/**
* Gets all comments.
*/
getAllComments() {
const { ctx, allTokens, cacheAllComments } = this[PRIVATE];
if (cacheAllComments) return cacheAllComments;
const result = [];
for (const token of allTokens) if (ctx.isComment(token)) result.push(token);
this[PRIVATE].cacheAllComments = result;
return result;
}
getFirstToken(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[1]);
let skipped = 0;
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
getFirstTokens(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[1]);
const result = [];
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.push(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
getLastToken(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[1]);
let skipped = 0;
for (let i = endIndex; i >= startIndex && i >= 0; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
getLastTokens(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[1]);
const result = [];
for (let i = endIndex; i >= startIndex && i >= 0; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.unshift(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
/**
* Gets the token that follows a given node or token.
*/
getTokenAfter(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[1]);
let skipped = 0;
for (let i = startIndex; i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
getTokensAfter(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[1]);
const result = [];
for (let i = startIndex; i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.push(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
/**
* Gets the token that precedes a given node or token.
*/
getTokenBefore(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[0]);
let skipped = 0;
for (let i = endIndex; i >= 0; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
/**
* Gets the `count` tokens that precedes a given node or token.
*/
getTokensBefore(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[0]);
const result = [];
for (let i = endIndex; i >= 0; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.unshift(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
getFirstTokenBetween(left, right, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
let skipped = 0;
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
getFirstTokensBetween(left, right, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
const result = [];
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.push(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
getLastTokenBetween(left, right, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, skip } = normalizeSkipOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
let skipped = 0;
for (let i = endIndex; i >= startIndex; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
if (skipped < skip) {
skipped++;
continue;
}
return token;
}
return null;
}
getLastTokensBetween(left, right, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
const result = [];
for (let i = endIndex; i >= startIndex; i--) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.unshift(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
/**
* Gets all tokens that are related to the given node.
*/
getTokens(node, options) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(options, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, node.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, node.range[1]);
const result = [];
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.push(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
/**
* Gets all of the tokens between two non-overlapping nodes.
*/
getTokensBetween(left, right, paddingOrOptions) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const { filter, count } = normalizeCountOptions(paddingOrOptions, ctx);
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
const result = [];
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (filter && !filter(token)) continue;
result.push(token);
if (count > 0 && result.length >= count) break;
}
return result;
}
/**
* Gets all comment tokens inside the given node or token.
*/
getCommentsInside(nodeOrToken) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, nodeOrToken.range[0]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, nodeOrToken.range[1]);
const result = [];
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (ctx.isComment(token)) result.push(token);
}
return result;
}
/**
* Gets all comment tokens directly before the given node or token.
*/
getCommentsBefore(nodeOrToken) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const endIndex = getLastIndex(allTokens, tokenStartToIndex, nodeOrToken.range[0]);
const result = [];
for (let i = endIndex; i >= 0; i--) {
const token = allTokens[i];
if (ctx.isComment(token)) result.unshift(token);
else break;
}
return result;
}
/**
* Gets all comment tokens directly after the given node or token.
*/
getCommentsAfter(nodeOrToken) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, nodeOrToken.range[1]);
const result = [];
for (let i = startIndex; i < allTokens.length; i++) {
const token = allTokens[i];
if (ctx.isComment(token)) result.push(token);
else break;
}
return result;
}
/**
* Checks if there are any comment tokens between two non-overlapping nodes.
*/
commentsExistBetween(left, right) {
const { ctx, allTokens, tokenStartToIndex } = this[PRIVATE];
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (ctx.isComment(token)) return true;
}
return false;
}
/**
* Checks if there is whitespace between two non-overlapping nodes.
*/
isSpaceBetween(left, right) {
if (left.range[1] >= right.range[0]) return false;
const { allTokens, tokenStartToIndex } = this[PRIVATE];
const startIndex = getFirstIndex(allTokens, tokenStartToIndex, left.range[1]);
const endIndex = getLastIndex(allTokens, tokenStartToIndex, right.range[0]);
let prev = left;
for (let i = startIndex; i <= endIndex && i < allTokens.length; i++) {
const token = allTokens[i];
if (prev.range[1] < token.range[0]) return true;
prev = token;
}
return prev.range[1] < right.range[0];
}
};
//#endregion
//#region package.json
var name$1 = "@ota-meshi/ast-token-store";
var version$1 = "0.3.0";
//#endregion
//#region src/meta.ts
var meta_exports = /* @__PURE__ */ __exportAll({
name: () => name,
version: () => version
});
const name = name$1;
const version = version$1;
//#endregion
//#region src/index.ts
const meta = { ...meta_exports };
//#endregion
export { TokenStore, meta };