Skip to content

Commit 590ddb7

Browse files
committed
[fix] Extract source code fragments from strings instead of bytes, fix #99
1 parent adcd24c commit 590ddb7

File tree

2 files changed

+32
-42
lines changed

2 files changed

+32
-42
lines changed

src/main/java/se/kth/spork/cli/SourceExtractor.java

+29-40
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package se.kth.spork.cli;
22

3+
import spoon.reflect.cu.CompilationUnit;
34
import spoon.reflect.cu.SourcePosition;
45
import spoon.reflect.declaration.CtElement;
56

67
import java.io.IOException;
78
import java.nio.charset.Charset;
8-
import java.util.Arrays;
99
import java.util.List;
1010

1111
/**
@@ -42,6 +42,24 @@ static String getOriginalSource(CtElement elem) {
4242
return getOriginalSource(pos, pos);
4343
}
4444

45+
/**
46+
* Get the original source code fragment starting at start and ending at end, including indentation if start is
47+
* the first element on its source code line.
48+
*
49+
* @param start The source position of the first element.
50+
* @param end The source position of the last element.
51+
* @return The source code fragment starting at start and ending at end, including leading indentation.
52+
* @throws IOException
53+
*/
54+
private static String getOriginalSource(SourcePosition start, SourcePosition end) {
55+
CompilationUnit cu = start.getCompilationUnit();
56+
String source = cu.getOriginalSourceCode();
57+
int startChar = precededByIndentation(source, start) ?
58+
getLineStartIdx(start) : start.getSourceStart();
59+
int endChar = end.getSourceEnd();
60+
return source.substring(startChar, endChar + 1);
61+
}
62+
4563
/**
4664
* Return the indentation count for this element. This is a bit hit-and-miss, but it usually works. It finds
4765
* the line that the element starts on, and counts the amount of indentation characters until the first character
@@ -53,7 +71,7 @@ static String getOriginalSource(CtElement elem) {
5371
*/
5472
static int getIndentation(CtElement elem) {
5573
SourcePosition pos = getSourcePos(elem);
56-
byte[] fileBytes = pos.getCompilationUnit().getOriginalSourceCode().getBytes(Charset.defaultCharset());
74+
String source = pos.getCompilationUnit().getOriginalSourceCode();
5775
int count = 0;
5876

5977
int[] lineSepPositions = pos.getCompilationUnit().getLineSeparatorPositions();
@@ -63,8 +81,8 @@ static int getIndentation(CtElement elem) {
6381

6482

6583
while (current + count < pos.getSourceStart()) {
66-
byte b = fileBytes[current + count];
67-
if (!isIndentation(b)) {
84+
char c = source.charAt(current + count);
85+
if (!isIndentation(c)) {
6886
break;
6987
}
7088
++count;
@@ -86,47 +104,18 @@ private static SourcePosition getSourcePos(CtElement elem) {
86104
return pos;
87105
}
88106

89-
private static String getOriginalSource(SourcePosition start, SourcePosition end) {
90-
byte[] source = start.getCompilationUnit().getOriginalSourceCode().getBytes(Charset.defaultCharset());
91-
return getOriginalSource(start, end, source);
92-
}
93-
94-
/**
95-
* Get the original source code fragment starting at start and ending at end, including indentation if start is
96-
* the first element on its source code line.
97-
*
98-
* @param start The source position of the first element.
99-
* @param end The source position of the last element.
100-
* @return The source code fragment starting at start and ending at end, including leading indentation.
101-
* @throws IOException
102-
*/
103-
private static String getOriginalSource(SourcePosition start, SourcePosition end, byte[] source) {
104-
int startByte = precededByIndentation(source, start) ?
105-
getLineStartByte(start) : start.getSourceStart();
106-
int endByte = end.getSourceEnd();
107-
108-
if (isIndentation(source[startByte])) {
109-
startByte++;
110-
endByte++;
111-
}
112-
113-
byte[] content = Arrays.copyOfRange(source, startByte, endByte + 1);
114-
115-
return new String(content, Charset.defaultCharset());
116-
}
117-
118-
private static boolean precededByIndentation(byte[] source, SourcePosition pos) {
119-
int lineStartByte = getLineStartByte(pos);
107+
private static boolean precededByIndentation(String source, SourcePosition pos) {
108+
int lineStartIdx = getLineStartIdx(pos);
120109

121-
for (int i = lineStartByte; i < pos.getSourceStart(); i++) {
122-
if (!isIndentation(source[i])) {
110+
for (int i = lineStartIdx; i < pos.getSourceStart(); i++) {
111+
if (!isIndentation(source.charAt(i))) {
123112
return false;
124113
}
125114
}
126115
return true;
127116
}
128117

129-
private static int getLineStartByte(SourcePosition pos) {
118+
private static int getLineStartIdx(SourcePosition pos) {
130119
if (pos.getLine() == 1)
131120
return 0;
132121

@@ -140,7 +129,7 @@ private static int getLineStartByte(SourcePosition pos) {
140129
return lineSepPositions[current];
141130
}
142131

143-
private static boolean isIndentation(byte b) {
144-
return b == ' ' || b == '\t';
132+
private static boolean isIndentation(char c) {
133+
return c == ' ' || c == '\t';
145134
}
146135
}

src/main/java/se/kth/spork/cli/SporkPrettyPrinter.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ public SporkPrettyPrinter scan(CtElement e) {
6464
return this;
6565
} else if (e.getMetadata(SpoonTreeBuilder.SINGLE_REVISION_KEY) != null &&
6666
(e instanceof CtMethod || e instanceof CtField)) {
67-
String originalSource = SourceExtractor.getOriginalSource(e);
68-
printerHelper.writeRawSourceCode(originalSource, SourceExtractor.getIndentation(e));
67+
CtElement origNode = (CtElement) e.getMetadata(SpoonTreeBuilder.ORIGINAL_NODE_KEY);
68+
String originalSource = SourceExtractor.getOriginalSource(origNode);
69+
printerHelper.writeRawSourceCode(originalSource, SourceExtractor.getIndentation(origNode));
6970
return this;
7071
}
7172

0 commit comments

Comments
 (0)