Skip to content

Commit 85ae1b1

Browse files
committed
Rewrite using line start offsets (h/t @DavyLandman)
1 parent 6b61adf commit 85ae1b1

File tree

2 files changed

+21
-40
lines changed

2 files changed

+21
-40
lines changed

rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/locations/impl/ArrayLineOffsetMap.java

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
import java.util.ArrayList;
3030
import java.util.Arrays;
31-
import java.util.stream.IntStream;
3231

3332
import org.apache.commons.lang3.tuple.Pair;
3433
import org.rascalmpl.vscode.lsp.util.locations.LineColumnOffsetMap;
@@ -37,13 +36,13 @@ public class ArrayLineOffsetMap implements LineColumnOffsetMap {
3736
private final IntArray lines;
3837
private final ArrayList<IntArray> wideColumnOffsets;
3938
private final ArrayList<IntArray> wideColumnOffsetsInverse;
40-
private final IntArray lineLengths;
39+
private final IntArray lineStartOffsets;
4140

42-
public ArrayLineOffsetMap(IntArray lines, ArrayList<IntArray> wideColumnOffsets, ArrayList<IntArray> wideColumnOffsetsInverse, IntArray lineLengths) {
41+
public ArrayLineOffsetMap(IntArray lines, ArrayList<IntArray> wideColumnOffsets, ArrayList<IntArray> wideColumnOffsetsInverse, IntArray lineStartOffsets) {
4342
this.lines = lines;
4443
this.wideColumnOffsets = wideColumnOffsets;
4544
this.wideColumnOffsetsInverse = wideColumnOffsetsInverse;
46-
this.lineLengths = lineLengths;
45+
this.lineStartOffsets = lineStartOffsets;
4746
}
4847

4948
@Override
@@ -83,27 +82,8 @@ public int translateInverseColumn(int line, int column, boolean isEnd) {
8382
public Pair<Integer, Integer> calculateInverseOffsetLength(int beginLine, int beginColumn, int endLine, int endColumn) {
8483
assert beginLine <= endLine : "beginLine cannot be larger than endLine";
8584

86-
int startOffset = 0;
87-
int endOffset = 0;
88-
89-
for (int line = 0; line <= endLine; line++) {
90-
int lineLength = translateInverseColumn(line, lineLengths.data[line], true);
91-
if (line < beginLine) {
92-
startOffset += lineLength;
93-
endOffset += lineLength;
94-
} else if (line == beginLine) {
95-
startOffset += translateInverseColumn(line, beginColumn, false);
96-
endOffset += line == endLine
97-
? translateInverseColumn(line, endColumn, true)
98-
: lineLength;
99-
} else if (line < endLine) {
100-
// beginLine < line < endLine
101-
endOffset += lineLength;
102-
} else {
103-
// line == endLine && beginLine != endLine
104-
endOffset += translateInverseColumn(line, endColumn, true);
105-
}
106-
}
85+
int startOffset = lineStartOffsets.get(beginLine) + translateInverseColumn(beginLine, beginColumn, false);
86+
int endOffset = lineStartOffsets.get(endLine) + translateInverseColumn(endLine, endColumn, true);
10787

10888
return Pair.of(startOffset, endOffset - startOffset);
10989
}
@@ -113,22 +93,18 @@ public static LineColumnOffsetMap build(String contents) {
11393
int line = 0;
11494
int column = 0;
11595
char prev = '\0';
116-
int lineLength = 0;
11796
GrowingIntArray linesWithSurrogate = new GrowingIntArray();
11897
ArrayList<IntArray> linesMap = new ArrayList<>(0);
11998
ArrayList<IntArray> inverseLinesMap = new ArrayList<>(0);
12099
GrowingIntArray currentLine = new GrowingIntArray();
121-
GrowingIntArray lineLengths = new GrowingIntArray();
100+
GrowingIntArray lineStartOffsets = new GrowingIntArray();
122101

102+
lineStartOffsets.add(0);
123103
for(int i = 0, n = contents.length() ; i < n ; i++) {
124104
char c = contents.charAt(i);
125105
if (c == '\n' || c == '\r') {
126106
if (c != prev && (prev == '\r' || prev == '\n')) {
127-
lineLength += 1; // 2 for \r\n
128107
continue; // multichar newline skip it
129-
} else {
130-
lineLengths.add(lineLength + 1);
131-
lineLength = 0;
132108
}
133109
if (!currentLine.isEmpty()) {
134110
linesWithSurrogate.add(line);
@@ -138,15 +114,14 @@ public static LineColumnOffsetMap build(String contents) {
138114
}
139115
line++;
140116
column = 0;
117+
lineStartOffsets.add(i + 1);
141118
}
142119
else {
143120
column++;
144-
lineLength++;
145121
if (Character.isHighSurrogate(c) && (i + 1) < n && Character.isLowSurrogate(contents.charAt(i + 1))) {
146122
// full surrogate pair, register it, and skip the next char
147123
currentLine.add(column);
148124
i++;
149-
lineLength++;
150125
}
151126
}
152127
prev = c;
@@ -157,14 +132,13 @@ public static LineColumnOffsetMap build(String contents) {
157132
linesMap.add(currentLine.build());
158133
inverseLinesMap.add(currentLine.buildInverse());
159134
}
160-
lineLengths.add(lineLength);
161135
if (linesMap.isEmpty()) {
162-
return EMPTY_MAP(lineLengths.build());
136+
return EMPTY_MAP(lineStartOffsets.build());
163137
}
164-
return new ArrayLineOffsetMap(linesWithSurrogate.build(), linesMap, inverseLinesMap, lineLengths.build());
138+
return new ArrayLineOffsetMap(linesWithSurrogate.build(), linesMap, inverseLinesMap, lineStartOffsets.build());
165139
}
166140

167-
private static LineColumnOffsetMap EMPTY_MAP(IntArray lineLengths) {
141+
private static LineColumnOffsetMap EMPTY_MAP(IntArray lineStartOffsets) {
168142
return new LineColumnOffsetMap(){
169143
@Override
170144
public int translateColumn(int line, int column, boolean atEnd) {
@@ -176,8 +150,8 @@ public int translateInverseColumn(int line, int column, boolean isEnd) {
176150
}
177151
@Override
178152
public Pair<Integer, Integer> calculateInverseOffsetLength(int beginLine, int beginColumn, int endLine, int endColumn) {
179-
final int beginOffset = beginColumn + IntStream.of(lineLengths.data).limit(beginLine).sum();
180-
final int endOffset = endColumn + IntStream.of(lineLengths.data).limit(endLine).sum();
153+
final int beginOffset = beginColumn + lineStartOffsets.get(beginLine);
154+
final int endOffset = endColumn + lineStartOffsets.get(endLine);
181155
return Pair.of(beginOffset, endOffset - beginOffset);
182156
}
183157

@@ -232,6 +206,13 @@ public IntArray(int[] data, int length) {
232206
this.length = length;
233207
}
234208

209+
public int get(int i) {
210+
if (i < 0 || i >= length) {
211+
throw new IndexOutOfBoundsException(String.format("Cannot get element at %d; IntArray has %d elements", i, this.length));
212+
}
213+
return data[i];
214+
}
215+
235216
/**
236217
* search for key, assume it's sorted data
237218
* @return >= 0 in case of exact match, below 0 is the insert point

rascal-lsp/src/test/java/engineering/swat/rascal/lsp/util/LineColumnOffsetMapTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public void singleWideCharInverse() {
7474
assertEquals(4, map.translateInverseColumn(0, 5, false));
7575
assertEquals(Pair.of(2, 1), map.calculateInverseOffsetLength(0, 2, 0, 4));
7676
assertEquals(Pair.of(3, 1), map.calculateInverseOffsetLength(0, 4, 0, 5));
77-
assertEquals(Pair.of(0, 11), map.calculateInverseOffsetLength(0, 0, 1, 6));
77+
assertEquals(Pair.of(0, 11), map.calculateInverseOffsetLength(0, 0, 1, 5));
7878
}
7979

8080

0 commit comments

Comments
 (0)