FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Handle edge cases in offset mapping · beetlecap/processing@4254acb · GitHub

Repository navigation

Commit 4254acb

Browse files
committed
Handle edge cases in offset mapping
1 parent acb2671 commit 4254acb

4 files changed

Lines changed: 111 additions & 54 deletions

File tree

‎java/src/processing/mode/java/pdex/JavaTextAreaPainter.java‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,15 @@ protected void paintErrorLine(Graphics gfx, int line, int x) {
305305
int rightTrimmedLength = trimRight(badCode).length();
306306
int leftTrimLength = rightTrimmedLength - trimmedLength;
307307

308+
// Fix offsets when bad code is just whitespace
309+
if (trimmedLength == 0) {
310+
leftTrimLength = 0;
311+
rightTrimmedLength = badCode.length();
312+
}
313+
308314
int x1 = textArea.offsetToX(line, goodCode.length() + leftTrimLength);
309315
int x2 = textArea.offsetToX(line, goodCode.length() + rightTrimmedLength);
316+
if (x1 == x2) x2 += fm.stringWidth(" ");
310317
int y1 = y + fm.getHeight() - 2;
311318

312319
if (line != problem.getLineNumber()) {

‎java/src/processing/mode/java/pdex/PDEX.java‎

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ private void handleCtrlClick(PreprocessedSketch ps, int tabIndex, int offset) {
188188
} else {
189189
Messages.log("found declaration, offset " + decl.getStartPosition() + ", name: " + declName);
190190
SketchInterval si = ps.mapJavaToSketch(declName);
191+
if (!ps.inRange(si)) return;
191192
EventQueue.invokeLater(() -> {
192193
editor.highlight(si.tabIndex, si.startTabOffset, si.stopTabOffset);
193194
});
@@ -315,59 +316,59 @@ void findUsageAndUpdateTree(PreprocessedSketch ps, IBinding binding) {
315316
break;
316317
}
317318

318-
String elementName = binding.getName();
319+
// Find usages, map to tree nodes, add to root node
320+
String bindingKey = binding.getKey();
321+
List<SketchInterval> intervals =
322+
findAllOccurrences(ps.compilationUnit, bindingKey).stream()
323+
.map(ps::mapJavaToSketch)
324+
// remove occurrences which fall into generated header
325+
.filter(ps::inRange)
326+
.collect(Collectors.toList());
327+
328+
int usageCount = intervals.size();
329+
330+
// Get element name from PDE code if possible, otherwise use one from Java
331+
String elementName = intervals.stream()
332+
.findAny()
333+
.map(si -> ps.pdeCode.substring(si.startPdeOffset, si.stopPdeOffset))
334+
.orElseGet(binding::getName);
319335

320336
// Create root node
321337
DefaultMutableTreeNode rootNode =
322338
new DefaultMutableTreeNode(bindingType + ": " + elementName);
323339

324-
int usageCount;
325-
326-
{ // Find usages, map to tree nodes, add to root node
327-
String bindingKey = binding.getKey();
328-
List<SketchInterval> intervals =
329-
findAllOccurrences(ps.compilationUnit, bindingKey).stream()
330-
.map(ps::mapJavaToSketch)
331-
// TODO: this has to be fixed with better token mapping
332-
// remove occurrences which fall into generated header
333-
.filter(in -> in.tabIndex != 0 ||
334-
(in.startTabOffset >= 0 && in.stopTabOffset > 0))
335-
.collect(Collectors.toList());
336-
337-
usageCount = intervals.size();
338-
339-
Map<Integer, List<ShowUsageTreeNode>> tabGroupedTreeNodes = intervals.stream()
340-
// Convert to TreeNodes
341-
.map(in -> ShowUsageTreeNode.fromSketchInterval(ps, in))
342-
// Group by tab
343-
.collect(Collectors.groupingBy(node -> node.tabIndex));
344-
345-
tabGroupedTreeNodes.entrySet().stream()
346-
// Sort by tab index
347-
.sorted(Comparator.comparing(Map.Entry::getKey))
348-
.map(entry -> {
349-
Integer tabIndex = entry.getKey();
350-
List<ShowUsageTreeNode> nodes = entry.getValue();
351-
352-
int count = nodes.size();
353-
String usageLabel = count == 1 ? "usage" : "usages";
354-
355-
// Create new DefaultMutableTreeNode for this tab
356-
String tabLabel = "<html><font color=#222222>" +
357-
ps.sketch.getCode(tabIndex).getPrettyName() +
358-
"</font> <font color=#999999>" + count + " " + usageLabel + "</font></html>";
359-
DefaultMutableTreeNode tabNode = new DefaultMutableTreeNode(tabLabel);
360-
361-
nodes.stream()
362-
// Convert TreeNodes to DefaultMutableTreeNodes
363-
.map(DefaultMutableTreeNode::new)
364-
// Add all as children of tab node
365-
.forEach(tabNode::add);
366-
return tabNode;
367-
})
368-
// Add all tab nodes as children of root node
369-
.forEach(rootNode::add);
370-
}
340+
intervals.stream()
341+
// Convert to TreeNodes
342+
.map(in -> ShowUsageTreeNode.fromSketchInterval(ps, in))
343+
// Group by tab index
344+
.collect(Collectors.groupingBy(node -> node.tabIndex))
345+
// Stream Map Entries of (tab index) <-> (List<ShowUsageTreeNode>)
346+
.entrySet().stream()
347+
// Sort by tab index
348+
.sorted(Comparator.comparing(Map.Entry::getKey))
349+
.map(entry -> {
350+
Integer tabIndex = entry.getKey();
351+
List<ShowUsageTreeNode> nodes = entry.getValue();
352+
353+
int count = nodes.size();
354+
String usageLabel = count == 1 ? "usage" : "usages";
355+
356+
// Create new DefaultMutableTreeNode for this tab
357+
String tabLabel = "<html><font color=#222222>" +
358+
ps.sketch.getCode(tabIndex).getPrettyName() +
359+
"</font> <font color=#999999>" + count + " " + usageLabel + "</font></html>";
360+
DefaultMutableTreeNode tabNode = new DefaultMutableTreeNode(tabLabel);
361+
362+
// Stream nodes belonging to this tab
363+
nodes.stream()
364+
// Convert TreeNodes to DefaultMutableTreeNodes
365+
.map(DefaultMutableTreeNode::new)
366+
// Add all as children of tab node
367+
.forEach(tabNode::add);
368+
return tabNode;
369+
})
370+
// Add all tab nodes as children of root node
371+
.forEach(rootNode::add);
371372

372373
TreeModel treeModel = new DefaultTreeModel(rootNode);
373374

@@ -654,6 +655,7 @@ void rename(PreprocessedSketch ps, IBinding binding, String newName) {
654655

655656
Map<Integer, List<SketchInterval>> mappedNodes = occurrences.stream()
656657
.map(ps::mapJavaToSketch)
658+
.filter(ps::inRange)
657659
.collect(Collectors.groupingBy(interval -> interval.tabIndex));
658660

659661
Sketch sketch = ps.sketch;
@@ -774,6 +776,7 @@ public void componentHidden(ComponentEvent e) {
774776
ASTNode node = (ASTNode) tnode.getUserObject();
775777
pps.whenDone(ps -> {
776778
SketchInterval si = ps.mapJavaToSketch(node);
779+
if (!ps.inRange(si)) return;
777780
EventQueue.invokeLater(() -> {
778781
editor.highlight(si.tabIndex, si.startTabOffset, si.stopTabOffset);
779782
});
@@ -886,11 +889,13 @@ private void handleSketchProblems(PreprocessedSketch ps) {
886889
int start = iproblem.getSourceStart();
887890
int stop = iproblem.getSourceEnd() + 1; // make it exclusive
888891
SketchInterval in = ps.mapJavaToSketch(start, stop);
892+
if (in == SketchInterval.BEFORE_START) return null;
889893
int line = ps.tabOffsetToTabLine(in.tabIndex, in.startTabOffset);
890894
Problem p = new Problem(iproblem, in.tabIndex, line);
891895
p.setPDEOffsets(in.startTabOffset, in.stopTabOffset);
892896
return p;
893897
})
898+
.filter(p -> p != null)
894899
.collect(Collectors.toList());
895900

896901
// Handle import suggestions

‎java/src/processing/mode/java/pdex/PreprocessedSketch.java‎

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public class PreprocessedSketch {
5050

5151

5252
public static class SketchInterval {
53+
54+
public static final SketchInterval BEFORE_START = new SketchInterval(-1, -1, -1, -1, -1);
55+
5356
private SketchInterval(int tabIndex,
5457
int startTabOffset, int stopTabOffset,
5558
int startPdeOffset, int stopPdeOffset) {
@@ -69,20 +72,42 @@ private SketchInterval(int tabIndex,
6972
}
7073

7174

75+
public boolean inRange(SketchInterval interval) {
76+
return interval != SketchInterval.BEFORE_START &&
77+
interval.stopPdeOffset < pdeCode.length();
78+
}
79+
80+
7281
public SketchInterval mapJavaToSketch(ASTNode node) {
7382
return mapJavaToSketch(node.getStartPosition(),
7483
node.getStartPosition() + node.getLength());
7584
}
7685

7786

7887
public SketchInterval mapJavaToSketch(int startJavaOffset, int stopJavaOffset) {
79-
boolean zeroLength = stopJavaOffset == startJavaOffset;
88+
int length = stopJavaOffset - startJavaOffset;
8089
int startPdeOffset = javaOffsetToPdeOffset(startJavaOffset);
81-
int stopPdeOffset = zeroLength ?
82-
javaOffsetToPdeOffset(stopJavaOffset) :
83-
javaOffsetToPdeOffset(stopJavaOffset-1)+1;
90+
int stopPdeOffset;
91+
if (length == 0) {
92+
stopPdeOffset = startPdeOffset;
93+
} else {
94+
stopPdeOffset = javaOffsetToPdeOffset(stopJavaOffset-1);
95+
if (stopPdeOffset >= 0 && (stopPdeOffset > startPdeOffset || length == 1)) {
96+
stopPdeOffset += 1;
97+
}
98+
}
99+
100+
if (startPdeOffset < 0 || stopPdeOffset < 0) {
101+
return SketchInterval.BEFORE_START;
102+
}
103+
84104
int tabIndex = pdeOffsetToTabIndex(startPdeOffset);
85105

106+
if (startPdeOffset >= pdeCode.length()) {
107+
startPdeOffset = pdeCode.length() - 1;
108+
stopPdeOffset = startPdeOffset + 1;
109+
}
110+
86111
return new SketchInterval(tabIndex,
87112
pdeOffsetToTabOffset(tabIndex, startPdeOffset),
88113
pdeOffsetToTabOffset(tabIndex, stopPdeOffset),
@@ -96,6 +121,7 @@ private int javaOffsetToPdeOffset(int javaOffset) {
96121

97122

98123
private int pdeOffsetToTabIndex(int pdeOffset) {
124+
pdeOffset = Math.max(0, pdeOffset);
99125
int tab = Arrays.binarySearch(tabStartOffsets, pdeOffset);
100126
if (tab < 0) {
101127
tab = -(tab + 1) - 1;

‎java/src/processing/mode/java/pdex/TextTransform.java‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,15 @@ private void buildIfNeeded(int inLength) {
132132
// Process encountered input edits
133133
while (inEdit != null && inOffset >= inEditOff) {
134134
inOffset += inEdit.fromLength;
135-
inMap.add(inEdit);
135+
if (inEdit.fromLength > 0) inMap.add(inEdit);
136136
inEdit = inIt.hasNext() ? inIt.next() : null;
137137
inEditOff = inEdit != null ? inEdit.fromOffset : inLength;
138138
}
139139

140140
// Process encountered output edits
141141
while (outEdit != null && inOffset >= outEditOff) {
142142
outEdit.toOffset = outOffset;
143-
outMap.add(outEdit);
143+
if (outEdit.toLength > 0) outMap.add(outEdit);
144144
outOffset += outEdit.toLength;
145145
outEdit = outIt.hasNext() ? outIt.next() : null;
146146
outEditOff = outEdit != null ? outEdit.toOffset : inLength;
@@ -225,13 +225,31 @@ private static class SimpleOffsetMapper implements OffsetMapper {
225225
private List<Edit> inMap = new ArrayList<>();
226226
private List<Edit> outMap = new ArrayList<>();
227227

228+
private int outputOffsetOfInputStart;
229+
private int inputOffsetOfOutputStart;
230+
228231
private SimpleOffsetMapper(List<Edit> inMap, List<Edit> outMap) {
229232
this.inMap.addAll(inMap);
230233
this.outMap.addAll(outMap);
234+
235+
Edit inStart = null;
236+
for (Edit in : this.inMap) {
237+
inStart = in;
238+
if (in.fromLength > 0) break;
239+
}
240+
outputOffsetOfInputStart = inStart == null ? 0 : inStart.toOffset;
241+
242+
Edit outStart = null;
243+
for (Edit out : this.inMap) {
244+
outStart = out;
245+
if (out.toLength > 0) break;
246+
}
247+
inputOffsetOfOutputStart = outStart == null ? 0 : outStart.fromOffset;
231248
}
232249

233250
@Override
234251
public int getInputOffset(int outputOffset) {
252+
if (outputOffset < outputOffsetOfInputStart) return -1;
235253
Edit searchKey = new Edit(0, 0, outputOffset, Integer.MAX_VALUE, null);
236254
int i = Collections.binarySearch(outMap, searchKey, OUTPUT_OFFSET_COMP);
237255
if (i < 0) {
@@ -246,6 +264,7 @@ public int getInputOffset(int outputOffset) {
246264

247265
@Override
248266
public int getOutputOffset(int inputOffset) {
267+
if (inputOffset < inputOffsetOfOutputStart) return -1;
249268
Edit searchKey = new Edit(inputOffset, Integer.MAX_VALUE, 0, 0, null);
250269
int i = Collections.binarySearch(inMap, searchKey, INPUT_OFFSET_COMP);
251270
if (i < 0) {

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL