Skip to content

Commit

Permalink
Fix error highlighting for missing tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
kshchepanovskyi committed Sep 24, 2016
1 parent a9d5b24 commit 594fd6b
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
Expand Up @@ -6,6 +6,7 @@
import org.antlr.jetbrains.adapter.lexer.PSIElementTypeFactory;
import org.antlr.jetbrains.adapter.lexer.RuleIElementType;
import org.antlr.jetbrains.adapter.lexer.TokenIElementType;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.ANTLRErrorListener;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
Expand All @@ -30,7 +31,7 @@
public class ANTLRParseTreeToPSIConverter implements ParseTreeListener {
protected final Language language;
protected final PsiBuilder builder;
protected List<SyntaxError> syntaxErrors;
protected Map<RecognitionException, SyntaxError> syntaxErrors;
protected final Deque<PsiBuilder.Marker> markers = new ArrayDeque<PsiBuilder.Marker>();

protected final List<TokenIElementType> tokenElementTypes;
Expand All @@ -48,8 +49,8 @@ public ANTLRParseTreeToPSIConverter(Language language, Parser parser, PsiBuilder

for (ANTLRErrorListener listener : parser.getErrorListeners()) {
if (listener instanceof SyntaxErrorListener) {
syntaxErrors = ((SyntaxErrorListener)listener).getSyntaxErrors();
for (SyntaxError error : syntaxErrors) {
syntaxErrors = ((SyntaxErrorListener)listener).getErrorMap();
for (SyntaxError error : syntaxErrors.values()) {
// record first error per token
int StartIndex = error.getOffendingSymbol().getStartIndex();
if ( !tokenToErrorMap.containsKey(StartIndex) ) {
Expand Down Expand Up @@ -115,6 +116,7 @@ public void visitTerminal(TerminalNode node) {
* prediction started (which we use to find syntax errors). So,
* SyntaxError objects return start not offending token in this case.
*/
@Override
public void visitErrorNode(ErrorNode node) {
ProgressIndicatorProvider.checkCanceled();

Expand Down Expand Up @@ -159,6 +161,16 @@ public void enterEveryRule(ParserRuleContext ctx) {
public void exitEveryRule(ParserRuleContext ctx) {
ProgressIndicatorProvider.checkCanceled();
PsiBuilder.Marker marker = markers.pop();
marker.done(getRuleElementTypes().get(ctx.getRuleIndex()));
if (ctx.exception != null) {
SyntaxError error = syntaxErrors.get(ctx.exception);
if (error != null) {
marker.error(error.getMessage());
} else {
// should not happen
marker.error("syntax error");
}
} else {
marker.done(getRuleElementTypes().get(ctx.getRuleIndex()));
}
}
}
Expand Up @@ -6,20 +6,23 @@
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Utils;

import java.util.ArrayList;
import java.util.List;
import java.util.*;

/** Traps errors from parsing language of plugin. E.g., for a Java plugin,
* this would catch errors when people type invalid Java code into .java file.
* This swallows the errors as the PSI tree has error nodes.
*/
public class SyntaxErrorListener extends BaseErrorListener {
private final List<SyntaxError> syntaxErrors = new ArrayList<SyntaxError>();
private final Map<RecognitionException, SyntaxError> syntaxErrors = new HashMap<RecognitionException, SyntaxError>();

public SyntaxErrorListener() {
}

public List<SyntaxError> getSyntaxErrors() {
return new ArrayList<SyntaxError>(syntaxErrors.values());
}

public Map<RecognitionException, SyntaxError> getErrorMap() {
return syntaxErrors;
}

Expand All @@ -29,11 +32,13 @@ public void syntaxError(Recognizer<?, ?> recognizer,
int line, int charPositionInLine,
String msg, RecognitionException e)
{
syntaxErrors.add(new SyntaxError(recognizer, (Token)offendingSymbol, line, charPositionInLine, msg, e));
syntaxErrors.put(e, new SyntaxError(recognizer, (Token)offendingSymbol, line, charPositionInLine, msg, e));
}



@Override
public String toString() {
return Utils.join(syntaxErrors.iterator(), "\n");
return Utils.join(syntaxErrors.values().iterator(), "\n");
}
}

0 comments on commit 594fd6b

Please sign in to comment.