Skip to content

Commit 0a0cbfc

Browse files
authored
Improve findClosestMapping (#50)
* find closest mapping should return null if no mapping is found * add test and fix another edge case * use .at as it checks boundaries * use lower_bound * code cleanup * remove segfault-handler for now... * more test * bump version
1 parent 509424b commit 0a0cbfc

7 files changed

+77
-29
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@parcel/source-map",
3-
"version": "2.0.0-alpha.4.20",
3+
"version": "2.0.0-alpha.4.21",
44
"main": "./dist/node.js",
55
"types": "index.d.ts",
66
"browser": "./dist/wasm-browser.js",

src/MappingContainer.cpp

+4-24
Original file line numberDiff line numberDiff line change
@@ -188,32 +188,12 @@ std::string MappingContainer::toVLQMappings() {
188188
}
189189

190190
Mapping MappingContainer::findClosestMapping(int lineIndex, int columnIndex) {
191-
if (lineIndex <= _generated_lines) {
191+
if (lineIndex <= _generated_lines && lineIndex >= 0) {
192192
auto &line = _mapping_lines.at(lineIndex);
193-
auto &segments = line._segments;
194-
unsigned int segmentsCount = segments.size();
195-
196-
int startIndex = 0;
197-
int stopIndex = segmentsCount - 1;
198-
int middleIndex = ((stopIndex + startIndex) / 2);
199-
while (startIndex < stopIndex) {
200-
Mapping &mapping = segments[middleIndex];
201-
int diff = mapping.generated.column - columnIndex;
202-
if (diff > 0) {
203-
--stopIndex;
204-
} else if (diff < 0) {
205-
++startIndex;
206-
} else {
207-
break;
208-
}
209-
210-
middleIndex = ((stopIndex + startIndex) / 2);
211-
}
212-
213-
return segments[middleIndex];
193+
return line.findClosestMapping(columnIndex);
194+
} else {
195+
return Mapping{Position{-1, -1}, Position{-1, -1}, -1, -1};
214196
}
215-
216-
return Mapping{Position{-1, -1}, Position{-1, -1}, -1, -1};
217197
}
218198

219199
int MappingContainer::getTotalSegments() {

src/MappingLine.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,42 @@ int MappingLine::lineNumber() {
3434
return _line_number;
3535
}
3636

37+
int MappingLine::lastColumn() {
38+
return _last_column;
39+
}
40+
41+
Mapping MappingLine::findClosestMapping(int columnIndex) {
42+
// Ensure mappings are sorted
43+
sort();
44+
45+
if (_segments.size() > 0) {
46+
Mapping searchValue = Mapping{Position{_line_number, columnIndex}, Position{-1, -1}, -1, -1};
47+
std::vector<Mapping>::iterator low = std::lower_bound(_segments.begin(), _segments.end(), searchValue, [](const Mapping& mappingA, const Mapping& mappingB){
48+
return mappingA.generated.column < mappingB.generated.column;
49+
});
50+
51+
if (low != _segments.end()) {
52+
Mapping currMapping = *low;
53+
if (++low != _segments.end()) {
54+
Mapping nextMapping = *low;
55+
56+
int nextMappingDiff = nextMapping.generated.column - columnIndex;
57+
int currMappingDiff = columnIndex - currMapping.generated.column;
58+
59+
if (nextMappingDiff < currMappingDiff) {
60+
return nextMapping;
61+
}
62+
}
63+
64+
return currMapping;
65+
} else {
66+
return _segments.at(0);
67+
}
68+
}
69+
70+
return Mapping{Position{-1, -1}, Position{-1, -1}, -1, -1};
71+
}
72+
3773
void MappingLine::clearMappings() {
3874
this->_segments.clear();
3975
this->_last_column = 0;

src/MappingLine.h

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class MappingLine {
1515

1616
int lineNumber();
1717

18+
int lastColumn();
19+
20+
Mapping findClosestMapping(int columnIndex);
21+
1822
std::vector<Mapping> _segments;
1923

2024
private:

src/node.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,12 @@ export default class NodeSourceMap extends SourceMap {
4646

4747
findClosestMapping(line: number, column: number): ?IndexedMapping<string> {
4848
let mapping = this.sourceMapInstance.findClosestMapping(line, column);
49-
let v = this.indexedMappingToStringMapping(mapping);
50-
return v;
49+
if (mapping.generated.line === -1 || mapping.generated.column === -1) {
50+
return null;
51+
} else {
52+
let v = this.indexedMappingToStringMapping(mapping);
53+
return v;
54+
}
5155
}
5256

5357
delete() {}

src/wasm.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default class WasmSourceMap extends SourceMap {
9696

9797
findClosestMapping(line: number, column: number): ?IndexedMapping<string> {
9898
let mapping = this.sourceMapInstance.findClosestMapping(line, column);
99-
if (mapping.generated.line === -1) {
99+
if (mapping.generated.line === -1 || mapping.generated.column === -1) {
100100
return null;
101101
} else {
102102
let m = { ...mapping };

test/find.test.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,14 @@ describe('SourceMap - Find', () => {
1010
names: [],
1111
});
1212

13-
let mapping = map.findClosestMapping(2, 14);
13+
let mapping = map.findClosestMapping(2, 8);
14+
assert.deepEqual(mapping, {
15+
generated: { line: 2, column: 9 },
16+
original: { line: 1, column: 7 },
17+
source: './helloworld.coffee',
18+
});
19+
20+
mapping = map.findClosestMapping(2, 14);
1421
assert.deepEqual(mapping, {
1522
generated: { line: 2, column: 14 },
1623
original: { line: 1, column: 12 },
@@ -23,5 +30,22 @@ describe('SourceMap - Find', () => {
2330
original: { line: 1, column: 0 },
2431
source: './helloworld.coffee',
2532
});
33+
34+
mapping = map.findClosestMapping(3, 15);
35+
assert.deepEqual(mapping, {
36+
generated: { line: 3, column: 0 },
37+
original: { line: 1, column: 0 },
38+
source: './helloworld.coffee',
39+
});
40+
41+
// Edge cases
42+
mapping = map.findClosestMapping(50, 15);
43+
assert.equal(mapping, null);
44+
45+
mapping = map.findClosestMapping(0, 0);
46+
assert.deepEqual(mapping, null);
47+
48+
mapping = map.findClosestMapping(-2, -6);
49+
assert.deepEqual(mapping, null);
2650
});
2751
});

0 commit comments

Comments
 (0)