public virtual QilNode Analyze(QilNode ndConstr, QilNode ndContent) {
if (ndConstr == null) {
// Root expression is analyzed
this.parentInfo = null;
this.xstates = PossibleXmlStates.WithinSequence;
this.withinElem = false;
Debug.Assert(ndContent != null);
ndContent = AnalyzeContent(ndContent);
}
else {
this.parentInfo = XmlILConstructInfo.Write(ndConstr);
if (ndConstr.NodeType == QilNodeType.Function) {
// Results of function should be pushed to writer
this.parentInfo.ConstructMethod = XmlILConstructMethod.Writer;
// Start with PossibleXmlStates.None and then add additional possible starting states
PossibleXmlStates xstates = PossibleXmlStates.None;
foreach (XmlILConstructInfo infoCaller in this.parentInfo.CallersInfo) {
if (xstates == PossibleXmlStates.None) {
xstates = infoCaller.InitialStates;
}
else if (xstates != infoCaller.InitialStates) {
xstates = PossibleXmlStates.Any;
}
// Function's results are pushed to Writer, so make sure that Invoke nodes' construct methods match
infoCaller.PushToWriterFirst = true;
}
this.parentInfo.InitialStates = xstates;
}
else {
// Build a standalone tree, with this constructor as its root
if (ndConstr.NodeType != QilNodeType.Choice)
this.parentInfo.InitialStates = this.parentInfo.FinalStates = PossibleXmlStates.WithinSequence;
// Don't stream Rtf; fully cache the Rtf and copy it into any containing tree in order to simplify XmlILVisitor.VisitRtfCtor
if (ndConstr.NodeType != QilNodeType.RtfCtor)
this.parentInfo.ConstructMethod = XmlILConstructMethod.WriterThenIterator;
}
// Set withinElem = true if analyzing element content
this.withinElem = (ndConstr.NodeType == QilNodeType.ElementCtor);
switch (ndConstr.NodeType) {
case QilNodeType.DocumentCtor: this.xstates = PossibleXmlStates.WithinContent; break;
case QilNodeType.ElementCtor: this.xstates = PossibleXmlStates.EnumAttrs; break;
case QilNodeType.AttributeCtor: this.xstates = PossibleXmlStates.WithinAttr; break;
case QilNodeType.NamespaceDecl: Debug.Assert(ndContent == null); break;
case QilNodeType.TextCtor: Debug.Assert(ndContent == null); break;
case QilNodeType.RawTextCtor: Debug.Assert(ndContent == null); break;
case QilNodeType.CommentCtor: this.xstates = PossibleXmlStates.WithinComment; break;
case QilNodeType.PICtor: this.xstates = PossibleXmlStates.WithinPI; break;
case QilNodeType.XsltCopy: this.xstates = PossibleXmlStates.Any; break;
case QilNodeType.XsltCopyOf: Debug.Assert(ndContent == null); break;
case QilNodeType.Function: this.xstates = this.parentInfo.InitialStates; break;
case QilNodeType.RtfCtor: this.xstates = PossibleXmlStates.WithinContent; break;
case QilNodeType.Choice: this.xstates = PossibleXmlStates.Any; break;
default: Debug.Assert(false, ndConstr.NodeType + " is not handled by XmlILStateAnalyzer."); break;
}
if (ndContent != null)
ndContent = AnalyzeContent(ndContent);
if (ndConstr.NodeType == QilNodeType.Choice)
AnalyzeChoice(ndConstr as QilChoice, this.parentInfo);
// Since Function will never be another node's content, set its final states here
if (ndConstr.NodeType == QilNodeType.Function)
this.parentInfo.FinalStates = this.xstates;
}
return ndContent;
}