Include line and column position in error messages.

This commit is contained in:
Jesse Wilson 2011-07-18 19:26:02 +00:00
parent 4b042671af
commit 415437810a
2 changed files with 73 additions and 1 deletions

View File

@ -204,6 +204,14 @@ public final class JsonReader implements Closeable {
private int pos = 0;
private int limit = 0;
/*
* Track the number of newlines and columns preceding the current buffer. To
* compute the line and column of a position in the buffer, compute the line
* and column in the buffer and add the preceding values.
*/
private int bufferStartLine;
private int bufferStartColumn;
private final List<JsonScope> stack = new ArrayList<JsonScope>();
{
push(JsonScope.EMPTY_DOCUMENT);
@ -817,6 +825,16 @@ public final class JsonReader implements Closeable {
* false.
*/
private boolean fillBuffer(int minimum) throws IOException {
// Before clobbering the old characters, update where buffer starts
for (int i = 0; i < pos; i++) {
if (buffer[i] == '\n') {
bufferStartLine++;
bufferStartColumn = 0;
} else {
bufferStartColumn++;
}
}
if (limit != pos) {
limit -= pos;
System.arraycopy(buffer, pos, buffer, 0, limit);
@ -835,6 +853,28 @@ public final class JsonReader implements Closeable {
return false;
}
private int getLineNumber() {
int result = bufferStartLine;
for (int i = 0; i < pos; i++) {
if (buffer[i] == '\n') {
result++;
}
}
return result + 1; // the first line is '1'
}
private int getColumnNumber() {
int result = bufferStartColumn;
for (int i = 0; i < pos; i++) {
if (buffer[i] == '\n') {
result = 0;
} else {
result++;
}
}
return result + 1; // the first column is '1'
}
private int nextNonWhitespace() throws IOException {
while (pos < limit || fillBuffer(1)) {
int c = buffer[pos++];
@ -1110,7 +1150,7 @@ public final class JsonReader implements Closeable {
* with this reader's content.
*/
private IOException syntaxError(String message) throws IOException {
throw new MalformedJsonException(message + " near " + getSnippet());
throw new MalformedJsonException(message + " @" + getLineNumber() + ":" + getColumnNumber());
}
private CharSequence getSnippet() {

View File

@ -18,6 +18,7 @@ package com.google.gson.stream;
import java.io.IOException;
import java.io.StringReader;
import java.util.Arrays;
import junit.framework.TestCase;
public final class JsonReaderTest extends TestCase {
@ -763,4 +764,35 @@ public final class JsonReaderTest extends TestCase {
} catch (IOException expected) {
}
}
public void testFailWithPosition() throws IOException {
JsonReader reader = new JsonReader(new StringReader("[\n\n\n\n\n0,}]"));
reader.beginArray();
reader.nextInt();
try {
reader.peek();
fail();
} catch (IOException expected) {
assertEquals("Expected literal value @6:3", expected.getMessage());
}
}
public void testFailWithPositionGreaterThanBufferSize() throws IOException {
String spaces = repeat(' ', 8192);
JsonReader reader = new JsonReader(new StringReader("[\n\n" + spaces + "\n\n\n0,}]"));
reader.beginArray();
reader.nextInt();
try {
reader.peek();
fail();
} catch (IOException expected) {
assertEquals("Expected literal value @6:3", expected.getMessage());
}
}
private String repeat(char c, int count) {
char[] array = new char[count];
Arrays.fill(array, c);
return new String(array);
}
}