@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
87 lines • 3.94 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TreeSitterExecutor = exports.DEFAULT_TREE_SITTER_WASM_PATH = exports.DEFAULT_TREE_SITTER_R_WASM_PATH = void 0;
const web_tree_sitter_1 = __importDefault(require("web-tree-sitter"));
const log_1 = require("../../../util/log");
const fs_1 = __importDefault(require("fs"));
exports.DEFAULT_TREE_SITTER_R_WASM_PATH = './node_modules/@eagleoutice/tree-sitter-r/tree-sitter-r.wasm';
exports.DEFAULT_TREE_SITTER_WASM_PATH = './node_modules/web-tree-sitter/tree-sitter.wasm';
const wasmLog = log_1.log.getSubLogger({ name: 'tree-sitter-wasm' });
/**
* Synchronous and (way) faster alternative to the {@link RShell} using tree-sitter.
*/
class TreeSitterExecutor {
name = 'tree-sitter';
parser;
static language;
/**
* Initializes the underlying tree-sitter parser. This only needs to be called once globally.
* @param config - The configuration for the tree-sitter engine, which can include paths to the wasm files.
* @param overrideWasmPath - The path to the tree-sitter-r wasm file, which takes precedence over the config and default paths if set.
* @param overrideTreeSitterWasmPath - The path to the tree-sitter wasm file, which takes precedence over the config and default paths if set.
*/
static async initTreeSitter(config, overrideWasmPath, overrideTreeSitterWasmPath) {
const treeSitterWasmPath = overrideTreeSitterWasmPath ?? config?.treeSitterWasmPath ?? exports.DEFAULT_TREE_SITTER_WASM_PATH;
// noinspection JSUnusedGlobalSymbols - this is used by emscripten, see https://emscripten.org/docs/api_reference/module.html
await web_tree_sitter_1.default.init({
locateFile: treeSitterWasmPath ? (path, prefix) => {
// allow setting a custom path for the tree sitter wasm file
if (path.endsWith('tree-sitter.wasm')) {
return treeSitterWasmPath;
}
return prefix + path;
} : undefined,
onAbort: (s) => wasmLog.error(`Tree-sitter wasm aborted: ${s}`),
print: (s) => wasmLog.debug(s),
printErr: (s) => wasmLog.error(s)
});
const wasmPath = overrideWasmPath ?? config?.wasmPath ?? exports.DEFAULT_TREE_SITTER_R_WASM_PATH;
TreeSitterExecutor.language = await web_tree_sitter_1.default.Language.load(wasmPath);
}
constructor() {
this.parser = new web_tree_sitter_1.default();
this.parser.setLanguage(TreeSitterExecutor.language);
}
rVersion() {
return Promise.resolve('none');
}
information(analyzer) {
return {
name: 'tree-sitter',
grammarVersion: this.treeSitterVersion(),
treeSitterQuery: async (source, force) => {
return this.query(source, ...(await analyzer.parse(force)).files.map(p => p.parsed));
}
};
}
treeSitterVersion() {
return this.parser.getLanguage().version;
}
parse(request) {
let sourceCode;
if (request.request === 'file') {
sourceCode = fs_1.default.readFileSync(request.content, 'utf8');
}
else {
sourceCode = request.content;
}
return this.parser.parse(sourceCode);
}
createQuery(source) {
return this.parser.getLanguage().query(source);
}
query(source, ...tree) {
const query = typeof source === 'string' ? this.createQuery(source) : source;
return tree
.flatMap(t => query.matches(t.rootNode))
.flatMap(m => m.captures);
}
close() {
this.parser.delete();
}
}
exports.TreeSitterExecutor = TreeSitterExecutor;
//# sourceMappingURL=tree-sitter-executor.js.map