Implement Wasm binding for Tree.getChangedRanges()

This commit is contained in:
Max Brunsfeld 2019-05-09 23:52:57 -07:00
parent 7de4985a27
commit 0d70b485c0
4 changed files with 94 additions and 5 deletions

View file

@ -74,6 +74,20 @@ static TSPoint unmarshal_point(const void **address) {
return point;
}
static void marshal_range(TSRange *range) {
range->start_byte = byte_to_code_unit(range->start_byte);
range->end_byte = byte_to_code_unit(range->end_byte);
range->start_point.column = byte_to_code_unit(range->start_point.column);
range->end_point.column = byte_to_code_unit(range->end_point.column);
}
static void unmarshal_range(TSRange *range) {
range->start_byte = code_unit_to_byte(range->start_byte);
range->end_byte = code_unit_to_byte(range->end_byte);
range->start_point.column = code_unit_to_byte(range->start_point.column);
range->end_point.column = code_unit_to_byte(range->end_point.column);
}
static TSInputEdit unmarshal_edit() {
TSInputEdit edit;
const void **address = TRANSFER_BUFFER;
@ -151,11 +165,7 @@ TSTree *ts_parser_parse_wasm(
};
if (range_count) {
for (unsigned i = 0; i < range_count; i++) {
TSRange *range = &ranges[i];
range->start_byte = code_unit_to_byte(range->start_byte);
range->end_byte = code_unit_to_byte(range->end_byte);
range->start_point.column = code_unit_to_byte(range->start_point.column);
range->end_point.column = code_unit_to_byte(range->end_point.column);
unmarshal_range(&ranges[i]);
}
ts_parser_set_included_ranges(self, ranges, range_count);
free(ranges);
@ -178,6 +188,16 @@ void ts_tree_edit_wasm(TSTree *tree) {
ts_tree_edit(tree, &edit);
}
void ts_tree_get_changed_ranges_wasm(TSTree *tree, TSTree *other) {
unsigned range_count;
TSRange *ranges = ts_tree_get_changed_ranges(tree, other, &range_count);
for (unsigned i = 0; i < range_count; i++) {
marshal_range(&ranges[i]);
}
TRANSFER_BUFFER[0] = (const void *)range_count;
TRANSFER_BUFFER[1] = (const void *)ranges;
}
/************************/
/* Section - TreeCursor */
/************************/

View file

@ -175,6 +175,26 @@ class Tree {
walk() {
return this.rootNode.walk();
}
getChangedRanges(other) {
if (other.constructor !== Tree) {
throw new TypeError('Argument must be a Tree');
}
C._ts_tree_get_changed_ranges_wasm(this[0], other[0]);
const count = getValue(TRANSFER_BUFFER, 'i32');
const buffer = getValue(TRANSFER_BUFFER + SIZE_OF_INT, 'i32');
const result = new Array(count);
if (count > 0) {
let address = buffer;
for (let i = 0; i < count; i++) {
result[i] = unmarshalRange(address);
address += SIZE_OF_RANGE;
}
C._free(buffer);
}
return result;
}
}
class Node {

View file

@ -81,5 +81,6 @@
"_ts_tree_cursor_start_position_wasm",
"_ts_tree_delete",
"_ts_tree_edit_wasm",
"_ts_tree_get_changed_ranges_wasm",
"_ts_tree_root_node_wasm"
]

View file

@ -81,6 +81,54 @@ describe("Tree", () => {
});
});
describe(".getChangedRanges(previous)", () => {
it("reports the ranges of text whose syntactic meaning has changed", () => {
let sourceCode = "abcdefg + hij";
tree = parser.parse(sourceCode);
assert.equal(
tree.rootNode.toString(),
"(program (expression_statement (binary_expression (identifier) (identifier))))"
);
sourceCode = "abc + defg + hij";
tree.edit({
startIndex: 2,
oldEndIndex: 2,
newEndIndex: 5,
startPosition: { row: 0, column: 2 },
oldEndPosition: { row: 0, column: 2 },
newEndPosition: { row: 0, column: 5 }
});
const tree2 = parser.parse(sourceCode, tree);
assert.equal(
tree2.rootNode.toString(),
"(program (expression_statement (binary_expression (binary_expression (identifier) (identifier)) (identifier))))"
);
const ranges = tree.getChangedRanges(tree2);
assert.deepEqual(ranges, [
{
startIndex: 0,
endIndex: "abc + defg".length,
startPosition: { row: 0, column: 0 },
endPosition: { row: 0, column: "abc + defg".length }
}
]);
tree2.delete();
});
it('throws an exception if the argument is not a tree', () => {
tree = parser.parse("abcdefg + hij");
assert.throws(() => {
tree.getChangedRanges({});
}, /Argument must be a Tree/);
})
});
describe(".walk()", () => {
let cursor