svelte-language-server
Version:
A language server for Svelte
95 lines • 4.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.gatherIdentifiers = exports.isInReactiveStatement = exports.isReactiveStatement = void 0;
exports.getStartOfNode = getStartOfNode;
exports.findNodeAtOffsetRange = findNodeAtOffsetRange;
exports.gatherDescendants = gatherDescendants;
const svelte2tsx_1 = require("svelte2tsx");
/**
* https://github.com/microsoft/typescript-go/blob/2a5e1cf9fe2261f2ad56871a6d2ed12d6ac34083/internal/scanner/scanner.go#L2473
* TODO: check if it's added to the ast package
*/
function getStartOfNode(tsAstModule, node, sourceFile) {
if (nodeIsMissing(tsAstModule, node)) {
return node.pos;
}
if (tsAstModule.isJSDoc(node) || node.kind === tsAstModule.SyntaxKind.JSDocText) {
return tsAstModule.skipTrivia(sourceFile.text, node.pos,
/*stopAfterLineBreak*/ false,
/*stopAtComments*/ true);
}
return tsAstModule.skipTrivia(sourceFile.text, node.pos,
/*stopAfterLineBreak*/ false,
/*stopAtComments*/ false,
/*inJSDoc*/ (node.flags & tsAstModule.NodeFlags.JSDoc) !== 0);
}
function nodeIsMissing(tsAstModule, node) {
return (!node ||
(node.pos === node.end && node.pos >= 0 && node.kind !== tsAstModule.SyntaxKind.EndOfFile));
}
function findNodeAtOffsetRange(tsAstModule, sourceFile, start, end) {
const nearest = tsAstModule.getTouchingToken(sourceFile, start);
if (nearest.end != end) {
let current = nearest;
while (current) {
if (current.end === end) {
return current;
}
current = current.parent;
}
}
}
/**
* Tests a node then its parent and successive ancestors for some respective predicates.
*/
function nodeAndParentsSatisfyRespectivePredicates(selfPredicate, ...predicates) {
return (tsAstModule, node) => {
let next = node;
return [selfPredicate, ...predicates].every((predicate) => {
if (!next) {
return false;
}
const current = next;
next = next.parent;
return predicate(tsAstModule, current);
});
};
}
const isRenderFunction = nodeAndParentsSatisfyRespectivePredicates((tsAstModule, node) => tsAstModule.isFunctionDeclaration(node) && node?.name?.text === svelte2tsx_1.internalHelpers.renderName, (tsAstModule, node) => node.kind === tsAstModule.SyntaxKind.SourceFile);
const isRenderFunctionBody = nodeAndParentsSatisfyRespectivePredicates((tsAstModule, node) => tsAstModule.isBlock(node), isRenderFunction);
exports.isReactiveStatement = nodeAndParentsSatisfyRespectivePredicates((tsAstModule, node) => tsAstModule.isLabeledStatement(node) && node.label.text === '$', or(
// function $$render() {
// $: x2 = __sveltets_2_invalidate(() => x * x)
// }
isRenderFunctionBody,
// function $$render() {
// ;() => {$: x, update();
// }
nodeAndParentsSatisfyRespectivePredicates((tsAstModule, node) => tsAstModule.isBlock(node), (tsAstModule, node) => tsAstModule.isArrowFunction(node), (tsAstModule, node) => tsAstModule.isExpressionStatement(node), isRenderFunctionBody)));
function or(...predicates) {
return (tsAstModule, node) => predicates.some((predicate) => predicate(tsAstModule, node));
}
function isSomeAncestor(tsAstModule, node, predicate) {
for (let parent = node.parent; parent; parent = parent.parent) {
if (predicate(tsAstModule, parent)) {
return true;
}
}
return false;
}
const isInReactiveStatement = (tsAstModule, node) => isSomeAncestor(tsAstModule, node, exports.isReactiveStatement);
exports.isInReactiveStatement = isInReactiveStatement;
function gatherDescendants(tsAstModule, node, predicate, dest = []) {
if (predicate(tsAstModule, node)) {
dest.push(node);
}
else {
node.forEachChild((child) => {
gatherDescendants(tsAstModule, child, predicate, dest);
});
}
return dest;
}
const gatherIdentifiers = (tsAstModule, node) => gatherDescendants(tsAstModule, node, (tsAstModule, node) => tsAstModule.isIdentifier(node));
exports.gatherIdentifiers = gatherIdentifiers;
//# sourceMappingURL=utils.js.map