Skip to content

Commit

Permalink
[fix] Extract source code fragments from strings instead of bytes, fix
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse committed Apr 12, 2020
1 parent adcd24c commit 590ddb7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 42 deletions.
69 changes: 29 additions & 40 deletions src/main/java/se/kth/spork/cli/SourceExtractor.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package se.kth.spork.cli;

import spoon.reflect.cu.CompilationUnit;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.declaration.CtElement;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

/**
Expand Down Expand Up @@ -42,6 +42,24 @@ static String getOriginalSource(CtElement elem) {
return getOriginalSource(pos, pos);
}

/**
* Get the original source code fragment starting at start and ending at end, including indentation if start is
* the first element on its source code line.
*
* @param start The source position of the first element.
* @param end The source position of the last element.
* @return The source code fragment starting at start and ending at end, including leading indentation.
* @throws IOException
*/
private static String getOriginalSource(SourcePosition start, SourcePosition end) {
CompilationUnit cu = start.getCompilationUnit();
String source = cu.getOriginalSourceCode();
int startChar = precededByIndentation(source, start) ?
getLineStartIdx(start) : start.getSourceStart();
int endChar = end.getSourceEnd();
return source.substring(startChar, endChar + 1);
}

/**
* Return the indentation count for this element. This is a bit hit-and-miss, but it usually works. It finds
* the line that the element starts on, and counts the amount of indentation characters until the first character
Expand All @@ -53,7 +71,7 @@ static String getOriginalSource(CtElement elem) {
*/
static int getIndentation(CtElement elem) {
SourcePosition pos = getSourcePos(elem);
byte[] fileBytes = pos.getCompilationUnit().getOriginalSourceCode().getBytes(Charset.defaultCharset());
String source = pos.getCompilationUnit().getOriginalSourceCode();
int count = 0;

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


while (current + count < pos.getSourceStart()) {
byte b = fileBytes[current + count];
if (!isIndentation(b)) {
char c = source.charAt(current + count);
if (!isIndentation(c)) {
break;
}
++count;
Expand All @@ -86,47 +104,18 @@ private static SourcePosition getSourcePos(CtElement elem) {
return pos;
}

private static String getOriginalSource(SourcePosition start, SourcePosition end) {
byte[] source = start.getCompilationUnit().getOriginalSourceCode().getBytes(Charset.defaultCharset());
return getOriginalSource(start, end, source);
}

/**
* Get the original source code fragment starting at start and ending at end, including indentation if start is
* the first element on its source code line.
*
* @param start The source position of the first element.
* @param end The source position of the last element.
* @return The source code fragment starting at start and ending at end, including leading indentation.
* @throws IOException
*/
private static String getOriginalSource(SourcePosition start, SourcePosition end, byte[] source) {
int startByte = precededByIndentation(source, start) ?
getLineStartByte(start) : start.getSourceStart();
int endByte = end.getSourceEnd();

if (isIndentation(source[startByte])) {
startByte++;
endByte++;
}

byte[] content = Arrays.copyOfRange(source, startByte, endByte + 1);

return new String(content, Charset.defaultCharset());
}

private static boolean precededByIndentation(byte[] source, SourcePosition pos) {
int lineStartByte = getLineStartByte(pos);
private static boolean precededByIndentation(String source, SourcePosition pos) {
int lineStartIdx = getLineStartIdx(pos);

for (int i = lineStartByte; i < pos.getSourceStart(); i++) {
if (!isIndentation(source[i])) {
for (int i = lineStartIdx; i < pos.getSourceStart(); i++) {
if (!isIndentation(source.charAt(i))) {
return false;
}
}
return true;
}

private static int getLineStartByte(SourcePosition pos) {
private static int getLineStartIdx(SourcePosition pos) {
if (pos.getLine() == 1)
return 0;

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

private static boolean isIndentation(byte b) {
return b == ' ' || b == '\t';
private static boolean isIndentation(char c) {
return c == ' ' || c == '\t';
}
}
5 changes: 3 additions & 2 deletions src/main/java/se/kth/spork/cli/SporkPrettyPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ public SporkPrettyPrinter scan(CtElement e) {
return this;
} else if (e.getMetadata(SpoonTreeBuilder.SINGLE_REVISION_KEY) != null &&
(e instanceof CtMethod || e instanceof CtField)) {
String originalSource = SourceExtractor.getOriginalSource(e);
printerHelper.writeRawSourceCode(originalSource, SourceExtractor.getIndentation(e));
CtElement origNode = (CtElement) e.getMetadata(SpoonTreeBuilder.ORIGINAL_NODE_KEY);
String originalSource = SourceExtractor.getOriginalSource(origNode);
printerHelper.writeRawSourceCode(originalSource, SourceExtractor.getIndentation(origNode));
return this;
}

Expand Down

0 comments on commit 590ddb7

Please sign in to comment.