public void ValidateTermination(BadTerminationHandler badTerminationHandler) { // Don't worry if the last object in the flow is a "TODO", // even if there are other loose ends in other places if (lastParsedSignificantObject is AuthorWarning) { return; } // By now, any sub-weaves will have passed loose ends up to the root weave (this). // So there are 2 possible situations: // - There are loose ends from somewhere in the flow. // These aren't necessarily "real" loose ends - they're weave points // that don't connect to any lower weave points, so we just // have to check that they terminate properly. // - This weave is just a list of content with no actual weave points, // so we just need to check that the list of content terminates. bool hasLooseEnds = looseEnds != null && looseEnds.Count > 0; if (hasLooseEnds) { foreach (var looseEnd in looseEnds) { var looseEndFlow = ContentThatFollowsWeavePoint(looseEnd); ValidateFlowOfObjectsTerminates(looseEndFlow, (Parsed.Object)looseEnd, badTerminationHandler); } } // No loose ends... is there any inner weaving at all? // If not, make sure the single content stream is terminated correctly else { // If there's any actual weaving, assume that content is // terminated correctly since we would've had a loose end otherwise foreach (var obj in content) { if (obj is IWeavePoint) { return; } } // Straight linear flow? Check it terminates ValidateFlowOfObjectsTerminates(content, this, badTerminationHandler); } }
void ValidateFlowOfObjectsTerminates(IEnumerable <Parsed.Object> objFlow, Parsed.Object defaultObj, BadTerminationHandler badTerminationHandler) { bool terminated = false; Parsed.Object terminatingObj = defaultObj; foreach (var flowObj in objFlow) { var divert = flowObj.Find <Divert> (d => !d.isThread && !d.isTunnel && !d.isFunctionCall && !(d.parent is DivertTarget)); if (divert != null) { terminated = true; } if (flowObj.Find <TunnelOnwards> () != null) { terminated = true; break; } terminatingObj = flowObj; } if (!terminated) { // Author has left a note to self here - clearly we don't need // to leave them with another warning since they know what they're doing. if (terminatingObj is AuthorWarning) { return; } badTerminationHandler(terminatingObj); } }