routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+465
@@ -0,0 +1,465 @@
|
||||
//#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 };
|
||||
Reference in New Issue
Block a user