Repository navigation
Expand file tree
/
Copy pathPruner.java
More file actions
154 lines (140 loc) · 5.91 KB
/
Copy pathPruner.java
File metadata and controls
154 lines (140 loc) · 5.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package org.javacs;
import com.sun.source.tree.*;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreeScanner;
import com.sun.source.util.Trees;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.regex.Pattern;
class Pruner {
private static String prune(CompilationUnitTree root, SourcePositions pos, StringBuilder buffer, long[] offsets) {
class Scan extends TreeScanner<Void, Void> {
boolean erasedAfterCursor = false;
boolean containsCursor(Tree node) {
var start = pos.getStartPosition(root, node);
var end = pos.getEndPosition(root, node);
for (var cursor : offsets) {
if (start <= cursor && cursor <= end) {
return true;
}
}
return false;
}
long lastCursorIn(Tree node) {
var start = pos.getStartPosition(root, node);
var end = pos.getEndPosition(root, node);
long last = -1;
for (var cursor : offsets) {
if (start <= cursor && cursor <= end) {
last = cursor;
}
}
if (last == -1) {
throw new RuntimeException(
String.format("No cursor in %s is between %d and %d", offsets, start, end));
}
return last;
}
void erase(long start, long end) {
for (int i = (int) start; i < end; i++) {
switch (buffer.charAt(i)) {
case '\r':
case '\n':
break;
default:
buffer.setCharAt(i, ' ');
}
}
}
@Override
public Void visitImport(ImportTree node, Void __) {
// Erase 'static' keyword so autocomplete works better
if (containsCursor(node) && node.isStatic()) {
var start = (int) pos.getStartPosition(root, node);
start = buffer.indexOf("static", start);
var end = start + "static".length();
erase(start, end);
}
return super.visitImport(node, null);
}
@Override
public Void visitBlock(BlockTree node, Void __) {
if (containsCursor(node)) {
super.visitBlock(node, null);
// When we find the deepest block that includes the cursor
if (!erasedAfterCursor) {
var cursor = lastCursorIn(node);
var start = cursor;
var end = pos.getEndPosition(root, node);
if (end >= buffer.length()) end = buffer.length() - 1;
// Find the next line
while (start < end && buffer.charAt((int) start) != '\n') start++;
// Find the end of the block
while (end > start && buffer.charAt((int) end) != '}') end--;
// Erase from next line to end of block
erase(start, end - 1);
erasedAfterCursor = true;
}
} else if (!node.getStatements().isEmpty()) {
var first = node.getStatements().get(0);
var last = node.getStatements().get(node.getStatements().size() - 1);
var start = pos.getStartPosition(root, first);
var end = pos.getEndPosition(root, last);
if (end >= buffer.length()) end = buffer.length() - 1;
erase(start, end);
}
return null;
}
@Override
public Void visitErroneous(ErroneousTree node, Void nothing) {
return super.scan(node.getErrorTrees(), nothing);
}
}
new Scan().scan(root, null);
return buffer.toString();
}
static String prune(URI file, int line, int character) {
// Parse file
var contents = FileStore.contents(file);
var task = Parser.parseTask(new SourceFileObject(file, contents));
CompilationUnitTree root;
try {
root = task.parse().iterator().next();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Erase all blocks that don't include line:character
var lines = root.getLineMap();
var cursor = lines.getPosition(line, character);
var pos = Trees.instance(task).getSourcePositions();
var buffer = new StringBuilder(contents);
return prune(root, pos, buffer, new long[] {cursor});
}
static String prune(URI file, String name) {
// Find all occurrences of name in contents
var contents = FileStore.contents(file);
var list = new ArrayList<Long>();
var pattern = Pattern.compile("\\b" + Pattern.quote(name) + "\\b");
var matcher = pattern.matcher(contents);
while (matcher.find()) {
list.add((long) matcher.start());
}
var offsets = new long[list.size()];
for (var i = 0; i < list.size(); i++) {
offsets[i] = list.get(i);
}
// Parse file
var task = Parser.parseTask(new SourceFileObject(file, contents));
CompilationUnitTree root;
try {
root = task.parse().iterator().next();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Erase all blocks that don't contain name
var buffer = new StringBuilder(contents);
var pos = Trees.instance(task).getSourcePositions();
return prune(root, pos, buffer, offsets);
}
}