Skip to content

Commit 5022284

Browse files
committed
Show error details + hint. #12
1 parent bef692f commit 5022284

1 file changed

Lines changed: 79 additions & 4 deletions

File tree

  • src/main/java/com/dashjoin/jsonata/cli

src/main/java/com/dashjoin/jsonata/cli/Main.java

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.io.InputStream;
88
import java.io.OutputStream;
99
import java.io.PrintStream;
10+
import java.io.PrintWriter;
11+
import java.io.StringWriter;
1012
import java.nio.file.Files;
1113
import java.util.Map;
1214

@@ -18,6 +20,7 @@
1820
import org.apache.commons.cli.Options;
1921

2022
import com.dashjoin.jsonata.Functions;
23+
import com.dashjoin.jsonata.JException;
2124
import com.dashjoin.jsonata.Jsonata;
2225
import com.dashjoin.jsonata.json.Json;
2326

@@ -27,6 +30,8 @@
2730
public class Main {
2831

2932
Options options;
33+
String expr;
34+
String exprFile;
3035

3136
Main() {
3237
initCli();
@@ -88,9 +93,9 @@ void run(String[] args) throws Throwable {
8893
printHelp();
8994
return;
9095
}
91-
String expr = cmd.getOptionValue("e");
92-
if (expr != null)
93-
expr = readFile(expr);
96+
exprFile = cmd.getOptionValue("e");
97+
if (exprFile != null)
98+
expr = readFile(exprFile);
9499
else
95100
expr = cmd.getArgList().get(0);
96101

@@ -191,6 +196,65 @@ void printVersion() {
191196
System.out.println(Version.getVersion());
192197
}
193198

199+
static class ErrorDetails {
200+
/**
201+
* Hint string showing the error location
202+
*/
203+
String hint;
204+
/**
205+
* Row of the error
206+
*/
207+
int row;
208+
/**
209+
* Column of the error
210+
*/
211+
int column;
212+
}
213+
214+
/**
215+
* Returns the error details: row, column,
216+
* and a hint that points to the error.
217+
* Supports multi-line expressions
218+
*
219+
* @param location (character index)
220+
* @return error details
221+
*/
222+
ErrorDetails getErrorDetails(int location) {
223+
int lineStart = -1;
224+
int line = 0;
225+
226+
StringWriter sw = new StringWriter();
227+
PrintWriter err = new PrintWriter(sw);
228+
229+
for (int i=0; i<expr.length(); i++) {
230+
if (i>=location)
231+
break;
232+
if ("\n\r".contains(""+expr.charAt(i))) {
233+
lineStart = i;
234+
line++;
235+
}
236+
}
237+
int col = location - lineStart - 1;
238+
for (int i=lineStart+1; i<expr.length(); i++) {
239+
if ("\n\r".contains(""+expr.charAt(i)))
240+
break;
241+
err.print(expr.charAt(i));
242+
}
243+
err.println();
244+
for (int i=0; i<col-1; i++) {
245+
err.print(" ");
246+
}
247+
err.println("^");
248+
249+
err.close();
250+
251+
ErrorDetails e = new ErrorDetails();
252+
e.hint = sw.toString();
253+
e.row = line;
254+
e.column = col;
255+
return e;
256+
}
257+
194258
/**
195259
* Main program
196260
*
@@ -199,6 +263,17 @@ void printVersion() {
199263
*/
200264
public static void main(String[] args) throws Throwable {
201265
Main main = new Main();
202-
main.run(args);
266+
try {
267+
main.run(args);
268+
} catch (JException jex) {
269+
ErrorDetails e = main.getErrorDetails(jex.getLocation());
270+
// Print error location so that VSCode directly jumps to the error
271+
// (if it's in a file "-e exprfile")
272+
System.err.println("JSONata error at "+
273+
(main.exprFile==null ? "expression":main.exprFile)+":"+(e.row+1)+"."+(e.column));
274+
System.err.println(jex.getMessage());
275+
System.err.println();
276+
System.err.println(e.hint);
277+
}
203278
}
204279
}

0 commit comments

Comments
 (0)