Skip to content

Commit

Permalink
Merge pull request #3766 from volodya-lombrozo/3743_err_location
Browse files Browse the repository at this point in the history
feat(#3743): Add Error Location for Custom Errors
  • Loading branch information
maxonfjvipon authored Dec 26, 2024
2 parents 55c88dc + 8bba152 commit d818680
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public final class ParsingException extends RuntimeException {
*/
private final int place;

/**
* Ctor.
* @param line The place
* @param msgs Messages
*/
ParsingException(final int line, final String... msgs) {
this(new IllegalStateException("Parsing error"), line, List.of(msgs));
}

/**
* Ctor.
* @param cause Cause of failure
Expand Down
112 changes: 79 additions & 33 deletions eo-parser/src/main/java/org/eolang/parser/XeEoListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import org.antlr.v4.runtime.ParserRuleContext;
Expand Down Expand Up @@ -78,9 +77,9 @@ public final class XeEoListener implements EoListener, Iterable<Directive> {
private final long start;

/**
* Errors map.
* Errors.
*/
private final Map<ParserRuleContext, String> errors;
private final List<ParsingException> errors;

/**
* Ctor.
Expand All @@ -90,7 +89,7 @@ public final class XeEoListener implements EoListener, Iterable<Directive> {
public XeEoListener(final String name) {
this.name = name;
this.dirs = new Directives();
this.errors = new HashMap<>(0);
this.errors = new ArrayList<>(0);
this.objects = new Objects.ObjXembly();
this.start = System.nanoTime();
}
Expand All @@ -107,16 +106,7 @@ public void enterProgram(final EoParser.ProgramContext ctx) {
public void exitProgram(final EoParser.ProgramContext ctx) {
this.dirs.xpath("/program").strict(1);
if (!this.errors.isEmpty()) {
this.dirs.addIf("errors").strict(1);
for (final Map.Entry<ParserRuleContext, String> error : this.errors.entrySet()) {
this.dirs
.add("error")
.attr("check", "eo-parser")
.attr("line", error.getKey().getStart().getLine())
.attr("severity", "critical")
.set(error.getValue());
}
this.dirs.up().up();
this.dirs.append(new DrErrors(this.errors));
}
this.dirs
.attr("ms", (System.nanoTime() - this.start) / (1000L * 1000L))
Expand Down Expand Up @@ -483,12 +473,16 @@ public void exitHapplicationTailReversed(final EoParser.HapplicationTailReversed
}

@Override
public void enterHapplicationTailReversedFirst(final EoParser.HapplicationTailReversedFirstContext ctx) {
public void enterHapplicationTailReversedFirst(
final EoParser.HapplicationTailReversedFirstContext ctx
) {
this.objects.enter();
}

@Override
public void exitHapplicationTailReversedFirst(final EoParser.HapplicationTailReversedFirstContext ctx) {
public void exitHapplicationTailReversedFirst(
final EoParser.HapplicationTailReversedFirstContext ctx
) {
this.objects.leave();
}

Expand Down Expand Up @@ -573,12 +567,16 @@ public void exitVapplicationArgBound(final EoParser.VapplicationArgBoundContext
}

@Override
public void enterVapplicationArgBoundCurrent(final EoParser.VapplicationArgBoundCurrentContext ctx) {
public void enterVapplicationArgBoundCurrent(
final EoParser.VapplicationArgBoundCurrentContext ctx
) {
// Nothing here
}

@Override
public void exitVapplicationArgBoundCurrent(final EoParser.VapplicationArgBoundCurrentContext ctx) {
public void exitVapplicationArgBoundCurrent(
final EoParser.VapplicationArgBoundCurrentContext ctx
) {
// Nothing here
}

Expand All @@ -603,22 +601,30 @@ public void exitVapplicationArgUnbound(final EoParser.VapplicationArgUnboundCont
}

@Override
public void enterVapplicationArgUnboundCurrent(final EoParser.VapplicationArgUnboundCurrentContext ctx) {
public void enterVapplicationArgUnboundCurrent(
final EoParser.VapplicationArgUnboundCurrentContext ctx
) {
// Nothing here
}

@Override
public void exitVapplicationArgUnboundCurrent(final EoParser.VapplicationArgUnboundCurrentContext ctx) {
public void exitVapplicationArgUnboundCurrent(
final EoParser.VapplicationArgUnboundCurrentContext ctx
) {
// Nothing here
}

@Override
public void enterVapplicationArgUnboundNext(final EoParser.VapplicationArgUnboundNextContext ctx) {
public void enterVapplicationArgUnboundNext(
final EoParser.VapplicationArgUnboundNextContext ctx
) {
// Nothing here
}

@Override
public void exitVapplicationArgUnboundNext(final EoParser.VapplicationArgUnboundNextContext ctx) {
public void exitVapplicationArgUnboundNext(
final EoParser.VapplicationArgUnboundNextContext ctx
) {
// Nothing here
}

Expand Down Expand Up @@ -707,12 +713,16 @@ public void exitAttributesAs(final EoParser.AttributesAsContext ctx) {
}

@Override
public void enterVapplicationArgHanonymBoundBody(final EoParser.VapplicationArgHanonymBoundBodyContext ctx) {
public void enterVapplicationArgHanonymBoundBody(
final EoParser.VapplicationArgHanonymBoundBodyContext ctx
) {
// Nothing here
}

@Override
public void exitVapplicationArgHanonymBoundBody(final EoParser.VapplicationArgHanonymBoundBodyContext ctx) {
public void exitVapplicationArgHanonymBoundBody(
final EoParser.VapplicationArgHanonymBoundBodyContext ctx
) {
// Nothing here
}

Expand Down Expand Up @@ -865,12 +875,16 @@ public void exitMethodTailOptional(final EoParser.MethodTailOptionalContext ctx)
}

@Override
public void enterVmethodHeadApplicationTail(final EoParser.VmethodHeadApplicationTailContext ctx) {
public void enterVmethodHeadApplicationTail(
final EoParser.VmethodHeadApplicationTailContext ctx
) {
// Nothing here
}

@Override
public void exitVmethodHeadApplicationTail(final EoParser.VmethodHeadApplicationTailContext ctx) {
public void exitVmethodHeadApplicationTail(
final EoParser.VmethodHeadApplicationTailContext ctx
) {
// Nothing here
}

Expand Down Expand Up @@ -1040,7 +1054,21 @@ public void enterAs(final EoParser.AsContext ctx) {
} else {
final int index = Integer.parseInt(ctx.INT().getText());
if (index < 0) {
this.errors.put(ctx, "Object binding can't be negative");
this.errors.add(
new ParsingException(
ctx.getStart().getLine(),
new MsgLocated(
ctx.getStart().getLine(),
ctx.getStart().getCharPositionInLine(),
"Object binding can't be negative"
).formatted(),
new MsgUnderlined(
XeEoListener.line(ctx),
ctx.getStart().getCharPositionInLine(),
ctx.getText().length()
).formatted()
)
);
}
has = String.format("α%d", index);
}
Expand Down Expand Up @@ -1084,18 +1112,14 @@ public void enterData(final EoParser.DataContext ctx) {
text.substring(1, text.length() - 1)
).getBytes(StandardCharsets.UTF_8)
);
} else if (ctx.TEXT() != null) {
} else {
base = "string";
final int indent = ctx.getStart().getCharPositionInLine();
data = new BytesToHex(
StringEscapeUtils.unescapeJava(
XeEoListener.trimMargin(text, indent)
).getBytes(StandardCharsets.UTF_8)
);
} else {
base = "unknown";
data = ctx::getText;
this.errors.put(ctx, String.format("Unknown data type: %s", ctx.getText()));
}
this.objects.prop("base", base).data(data.get());
}
Expand Down Expand Up @@ -1197,4 +1221,26 @@ private static String trimMargin(final String text, final int indent) {
}
return res.toString();
}

/**
* Get line from context.
* @param ctx Context
* @return Line
*/
private static String line(final ParserRuleContext ctx) {
final Token token = ctx.start;
final int number = token.getLine();
final String[] lines = token.getInputStream().toString().split("\n");
if (number > 0 && number <= lines.length) {
return lines[number - 1];
} else {
throw new IllegalArgumentException(
String.format(
"Line number '%s' out of bounds, total lines: %d",
number,
lines.length
)
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
# SOFTWARE.
---
line: 4
# @todo #3706:30min Add exact location of the error in the message.
# This message is already quite clear, but it would be better if it included
# the exact location of the error.
message: |-
Object binding can't be negative
[4:6] error: 'Object binding can't be negative'
42:-1
^^^
input: |
# No comments
[] > foo
Expand Down

1 comment on commit d818680

@0pdd
Copy link

@0pdd 0pdd commented on d818680 Dec 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 3706-9d5eb2d7 disappeared from eo-parser/src/test/resources/org/eolang/parser/eo-typos/broken-binding.yaml), that's why I closed #3743. Please, remember that the puzzle was not necessarily removed in this particular commit. Maybe it happened earlier, but we discovered this fact only now.

Please sign in to comment.