@krassowski/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
124 lines • 5.57 kB
JavaScript
import { position_at_offset } from '../positioning';
export function getIndexOfCaptureGroup(expression, matched_string, value_of_captured_group) {
// TODO: use https://github.com/tc39/proposal-regexp-match-indices once supported in >95% of browsers
// (probably around 2025)
// get index of the part that is being extracted to foreign document
let captured_groups = expression.exec(matched_string);
if (captured_groups == null) {
console.warn(`No capture group found for ${expression} in ${matched_string}`);
return -1;
}
let offset_in_match = 0;
// first element is a full match
let full_matched = captured_groups[0];
for (let group of captured_groups.slice(1)) {
if (typeof group === 'undefined') {
continue;
}
if (group === value_of_captured_group) {
offset_in_match += full_matched.indexOf(group);
break;
}
let group_end_offset = full_matched.indexOf(group) + group.length;
full_matched = full_matched.slice(group_end_offset);
offset_in_match += group_end_offset;
}
return offset_in_match;
}
export class RegExpForeignCodeExtractor {
constructor(options) {
this.language = options.language;
this.options = options;
this.global_expression = new RegExp(options.pattern, 'g');
this.test_expression = new RegExp(options.pattern, 'g');
this.expression = new RegExp(options.pattern);
this.standalone = this.options.is_standalone;
this.file_extension = this.options.file_extension;
}
has_foreign_code(code) {
let result = this.test_expression.test(code);
this.test_expression.lastIndex = 0;
return result;
}
extract_foreign_code(code) {
let lines = code.split('\n');
let extracts = new Array();
let started_from = this.global_expression.lastIndex;
let match = this.global_expression.exec(code);
let host_code_fragment;
let chosen_replacer;
let is_new_api_replacer = false;
if (typeof this.options.foreign_replacer !== 'undefined') {
chosen_replacer = this.options.foreign_replacer;
is_new_api_replacer = true;
}
else if (typeof this.options.foreign_capture_groups !== 'undefined') {
chosen_replacer = '$' + this.options.foreign_capture_groups.join('$');
is_new_api_replacer = true;
}
else if (this.options.extract_to_foreign) {
chosen_replacer = this.options.extract_to_foreign;
}
else {
console.warn(`Foreign replacer not defined for extractor: {this.expression} - this is deprecated; use 'foreign_replacer' to define it`);
return [];
}
while (match != null) {
let matched_string = match[0];
let position_shift = null;
let foreign_code_fragment = matched_string.replace(this.expression,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
chosen_replacer);
let prefix = '';
if (typeof this.options.extract_arguments !== 'undefined') {
prefix = matched_string.replace(this.expression,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.options.extract_arguments);
position_shift = position_at_offset(prefix.length, prefix.split('\n'));
}
// NOTE:
// match.index + matched_string.length === this.sticky_expression.lastIndex
let end_index = this.global_expression.lastIndex;
if (this.options.keep_in_host || this.options.keep_in_host == null) {
host_code_fragment = code.substring(started_from, end_index);
}
else {
if (started_from === match.index) {
host_code_fragment = '';
}
else {
host_code_fragment = code.substring(started_from, match.index) + '\n';
}
}
let foreign_code_group_value = foreign_code_fragment;
if (is_new_api_replacer) {
foreign_code_group_value = matched_string.replace(this.expression, '$' + Math.min(...this.options.foreign_capture_groups));
}
const foreign_group_index_in_match = getIndexOfCaptureGroup(this.expression, matched_string, foreign_code_group_value);
let start_offset = match.index + foreign_group_index_in_match;
let start = position_at_offset(start_offset, lines);
let end = position_at_offset(start_offset + foreign_code_fragment.length, lines);
extracts.push({
host_code: host_code_fragment,
foreign_code: prefix + foreign_code_fragment,
range: { start, end },
virtual_shift: position_shift
});
started_from = this.global_expression.lastIndex;
match = this.global_expression.exec(code);
}
if (started_from !== code.length) {
let final_host_code_fragment = code.substring(started_from, code.length);
extracts.push({
host_code: final_host_code_fragment,
foreign_code: null,
range: null,
virtual_shift: null
});
}
return extracts;
}
}
//# sourceMappingURL=regexp.js.map