Skip to content

NPE caused by InlineParsers #96

@spearce

Description

@spearce

I'm getting an NPE while parsing a simple document like:

foo {} is a "test" right?

The NPE seems to be caused by having two InlineParser extensions fire on the same paragraph of text. In this case I have an InlineParser extension on { and ". Code for the extensions is below. The NPE seems to be caused by the InlineParserImpl incorrectly creating the Node its passing into the second extension that fires on the paragraph. The node is not attached to any other node, it has no parent. Its not a member of the paragraph.

java.lang.NullPointerException
	at org.commonmark.node.Node.insertAfter(Node.java:89)
	at com.google.gitiles.doc.SmartQuotedExtension.quote(SmartQuotedExtension.java:51)
	at com.google.gitiles.doc.SmartQuotedExtension.access$0(SmartQuotedExtension.java:43)
	at com.google.gitiles.doc.SmartQuotedExtension$QuotedProcessor.process(SmartQuotedExtension.java:86)
	at org.commonmark.internal.InlineParserImpl.processDelimiters(InlineParserImpl.java:854)
	at org.commonmark.internal.InlineParserImpl.parse(InlineParserImpl.java:169)
	at org.commonmark.internal.ParagraphParser.parseInlines(ParagraphParser.java:61)
	at org.commonmark.internal.DocumentParser.processInlines(DocumentParser.java:410)
	at org.commonmark.internal.DocumentParser.finalizeAndProcess(DocumentParser.java:529)
	at org.commonmark.internal.DocumentParser.parse(DocumentParser.java:118)
	at org.commonmark.parser.Parser.parse(Parser.java:60)
public class NamedAnchorExtension implements ParserExtension {
  @Override
  public void extend(Parser.Builder builder) {
    builder.customDelimiterProcessor(new Processor());
  }

  private static class Processor implements DelimiterProcessor {
    @Override
    public char getOpeningCharacter() {
      return '{';
    }

    @Override
    public char getClosingCharacter() {
      return '}';
    }

    @Override
    public int getMinLength() {
      return 1;
    }

    @Override
    public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) {
      return 1;
    }

    @Override
    public void process(Text opener, Text closer, int delimiterUse) {
      // Silly yes, but simplified for this issue report.
      opener.insertAfter(new Text("{"));
      closer.insertBefore(new Text("}"));
    } 
}

public class SmartQuotedExtension implements ParserExtension {
  SmartQuotedExtension() {}

  @Override
  public void extend(Parser.Builder builder) {
    builder.customDelimiterProcessor(new QuotedProcessor(SINGLE, '\''));
    builder.customDelimiterProcessor(new QuotedProcessor(DOUBLE, '"'));
  }

  private static void quote(Type type, Text opener, Text closer) {
    SmartQuoted quote = new SmartQuoted();
    quote.setType(type);
    for (Node t = opener.getNext(); t != null && t != closer; ) {
      Node next = t.getNext();
      quote.appendChild(t);
      t = next;
    }
    opener.insertAfter(quote);
  }

  /** Parses single and double quoted strings for smart quotes. */
  private static class QuotedProcessor implements DelimiterProcessor {
    private final SmartQuoted.Type type;
    private final char delim;

    QuotedProcessor(SmartQuoted.Type type, char open) {
      this.type = type;
      this.delim = open;
    }

    @Override
    public char getOpeningCharacter() {
      return delim;
    }

    @Override
    public char getClosingCharacter() {
      return delim;
    }

    @Override
    public int getMinLength() {
      return 1;
    }

    @Override
    public int getDelimiterUse(DelimiterRun opener, DelimiterRun closer) {
      return 1;
    }

    @Override
    public void process(Text opener, Text closer, int delimiterUse) {
      quote(type, opener, closer);
    }
  }
}

public class SmartQuoted extends CustomNode {
  public enum Type {
    DOUBLE,
    SINGLE;
  }

  private Type type;

  public Type getType() {
    return type;
  }

  public void setType(Type type) {
    this.type = type;
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions