Files
vscode-debug-visualizer/data-extraction/src/js/api/default-extractors/StringRangeExtractor.ts
2023-03-24 14:06:22 +01:00

117 lines
2.6 KiB
TypeScript

import { DataExtractor, ExtractionCollector, DataExtractorContext } from "..";
import { LineColumnRange } from "../../../CommonDataTypes";
import { asData } from "../../helpers";
export class StringRangeExtractor implements DataExtractor {
readonly id = "stringRange";
getExtractions(
data: unknown,
collector: ExtractionCollector,
context: DataExtractorContext
): void {
if (!Array.isArray(data)) {
return;
}
if (typeof data[0] !== "string") {
return;
}
const text = data[0];
const decorations1: { range: LineColumnRange; label?: string }[] = [];
const decorations2: { range: LineColumnRange; label?: string }[] = [];
function offsetToLineColumn(offset: number) {
let line = 0;
let column = 0;
for (let idx = 0; idx < text.length; idx++) {
if (idx === offset) {
return { line, column };
}
if (text[idx] === "\n") {
line++;
column = 0;
} else {
column++;
}
}
return { line, column }; // TODO
}
if (
data.length === 2 &&
typeof data[1] === "object" &&
!Array.isArray(data[1])
) {
data = [data[0], ...Object.values(data[1])] as [
number | [number, number]
][];
}
for (let item of (data as (number | [number, number])[]).slice(1)) {
if (typeof item === "string") {
try {
item = context.evalFn(item);
} catch (e) {
return;
}
if (item === undefined) {
continue;
}
}
if (typeof item === "number") {
const pos = offsetToLineColumn(item);
decorations1.push({ range: { start: pos, end: pos } });
decorations2.push({
range: {
start: pos,
end: { line: pos.line, column: pos.column + 1 },
},
});
} else if (
Array.isArray(item) &&
item.length === 2 &&
typeof item[0] === "number" &&
typeof item[1] === "number"
) {
decorations1.push({
range: {
start: offsetToLineColumn(item[0]),
end: offsetToLineColumn(item[1]),
},
});
decorations2.push(decorations1[decorations1.length - 1]);
} else {
return;
}
}
collector.addExtraction({
priority: 1200,
id: "stringRange",
name: "String Range",
extractData() {
return asData({
kind: { text: true },
text,
decorations: decorations1,
});
},
});
collector.addExtraction({
priority: 1000,
id: "stringRangeFullCharacters",
name: "String Range (Full Character)",
extractData() {
return asData({
kind: { text: true },
text,
decorations: decorations2,
});
},
});
}
}