Skip to content

Commit

Permalink
Made the YAML parser recover from errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
lkishalmi committed Oct 15, 2021
1 parent c3e2a02 commit 2e9400a
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
package org.netbeans.modules.languages.yaml;

import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
Expand Down Expand Up @@ -103,7 +102,6 @@ static void replaceWithSpaces(StringBuilder source, String startToken, String en
if (startReplace == -1) {
return;
}

while (startReplace > -1) {
int endReplace = source.indexOf(endToken, startReplace) + 1;
if (endReplace > startReplace) {
Expand Down Expand Up @@ -178,28 +176,45 @@ YamlParserResult parse(String src, Snapshot snapshot) {

YamlParserResult result = new YamlParserResult(snapshot);

Deque<YamlSection> sources = new LinkedList<>();
LinkedList<YamlSection> sources = new LinkedList<>();
sources.push(new YamlSection(sb.toString()));
int sourceLength = Integer.MAX_VALUE;
int stallCounter = 0;
while (!sources.isEmpty()) {
int len = 0;
for (YamlSection source : sources) {
len += source.length();
}

YamlSection section = sources.pop();
try {
List<? extends StructureItem> items = section.collectItems();
result.addStructure(items);
} catch (ScannerException se) {
result.addError(section.processScannerException(snapshot, se));
// YamlSection after = section.after(se.getProblemMark().get().getIndex());
// YamlSection before = section.before(se.getContextMark().get().getIndex());
// if (!after.isEmpty()) sources.push(after);
// if (!before.isEmpty()) sources.push(before);
} catch (ParserException pe ){
result.addError(section.processParserException(snapshot, pe));
// sources.addAll(section.splitOnParserException(pe));
} catch (Exception ex) {
String message = ex.getMessage();
if (message != null && message.length() > 0) {
result.addError(processError(message, snapshot, 0));
if (len < sourceLength) {
sourceLength = len;
stallCounter = 0;
} else {
stallCounter++;
}
if (stallCounter < 2) {
YamlSection section = sources.pop();
try {
List<? extends StructureItem> items = section.collectItems();
result.addStructure(items);
} catch (ScannerException se) {
result.addError(section.processException(snapshot, se));
for (YamlSection part : section.splitOnException(se)) {
sources.push(part);
}
} catch (ParserException pe ){
result.addError(section.processException(snapshot, pe));
for (YamlSection part : section.splitOnException(pe)) {
sources.push(part);
}
} catch (Exception ex) {
String message = ex.getMessage();
if (message != null && message.length() > 0) {
result.addError(processError(message, snapshot, 0));
}
}
} else {
sources.clear();
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ public YamlParserResult(Snapshot snapshot) {
}

public void addError(Error error) {
errors.add(error);
boolean alreadyReported = false;
for (Error e : errors) {
if ((e.getStartPosition() <= error.getStartPosition()) && (e.getEndPosition() >= error.getStartPosition())) {
alreadyReported = true;
break;
}
}
if (!alreadyReported) {
errors.add(error);
}
}

public void addStructure(List<? extends StructureItem> items) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,21 @@ private YamlStructureItem processSequence(SequenceStartEvent evt) {
return item;
}

DefaultError processScannerException(Snapshot snapshot, ScannerException se) {
int contextIndex = getIndex(se.getContextMark());
DefaultError processException(Snapshot snapshot, ScannerException se) {
int problemIndex = getIndex(se.getProblemMark());
StringBuilder message = new StringBuilder(se.getContext());
message.append(", ").append(se.getProblem());
int contextIndex = problemIndex;
StringBuilder message = new StringBuilder();
if (se.getContext() != null) {
contextIndex = getIndex(se.getContextMark());
message.append(se.getContext()).append(", ");
}
message.append(se.getProblem());
char upper = Character.toUpperCase(message.charAt(0));
message.setCharAt(0, upper);
return new DefaultError(null, message.toString(), null, snapshot.getSource().getFileObject(), contextIndex, problemIndex, Severity.ERROR);
}

DefaultError processParserException(Snapshot snapshot, ParserException se) {
DefaultError processException(Snapshot snapshot, ParserException se) {
int problemIndex = se.getProblemMark().isPresent() ? getIndex(se.getProblemMark()) : 0;
int contextIndex = problemIndex;
StringBuilder message = new StringBuilder();
Expand All @@ -204,13 +208,23 @@ DefaultError processParserException(Snapshot snapshot, ParserException se) {
return new DefaultError(null, message.toString(), null, snapshot.getSource().getFileObject(), contextIndex, problemIndex, Severity.ERROR);
}

List<YamlSection> splitOnParserException(ParserException pe) {
List<YamlSection> splitOnException(ScannerException se) {
int problemIndex = se.getProblemMark().get().getIndex();
if (se.getContextMark().isPresent()) {
int contextIndex = se.getContextMark().get().getIndex();
return split(contextIndex, problemIndex);
} else {
return split(problemIndex, problemIndex);
}
}

List<YamlSection> splitOnException(ParserException pe) {
if (pe.getContextMark().isPresent()) {
int contextIndex = pe.getContextMark().get().getIndex();
return split(contextIndex, contextIndex + 1);
return split(contextIndex, contextIndex);
} else {
int problemIndex = pe.getProblemMark().get().getIndex();
return split(problemIndex, problemIndex + 1);
return split(problemIndex, problemIndex);
}
}

Expand All @@ -224,12 +238,12 @@ List<YamlSection> split(int a, int b) {
if (after.isEmpty()) {
before = before.trimTail();
}
if (!before.isEmpty()) {
ret.add(before);
}
if (!after.isEmpty()) {
ret.add(after);
}
if (!before.isEmpty()) {
ret.add(before);
}
return ret;
}

Expand Down

0 comments on commit 2e9400a

Please sign in to comment.