Because of the Spans contract that there is always at least one start/end position per doc, I considered adding a firstStartPosition method that should be called before the first nextStartPosition call.
That would reduce the need for the atFirstInCurrentDoc flag that is used in quite a few Spans, and that might help to avoid problems like this one.
Well, I'm not sure it would avoid all cases of this problem, which IMO is a trap in FilterSpans. If we return null in FilterSpans by default, thats also a trap (just a performance trap instead).
Separately, it might be a good idea, but maybe we should add the remaining two-phase support first (SpanOrQuery, SpanNotQuery) and then try to look at refactoring after have a clear picture of all the stuff involved? I started with this query because it seemed easiest. The next step would be to give SpanOr and SpanNot logic similar to DisjunctionScorer and ReqExclScorer. Another step after that is to see if they can share two-phase code (like SpanNear does with ConjunctionDISI).