in scala/scala-impl/src/org/jetbrains/plugins/scala/lang/lexer/ScalaLexer.java [175:331]
private LocateXmlTokenResult doLocateTokenInsideXml(
final int start,
@Nullable final IElementType type,
@NotNull final CharSequence tokenText
) {
--xmlSteps;
if (type == ScalaTokenTypesEx.SCALA_XML_CONTENT_START) {
final XmlTagValidator xmlTagValidator = new XmlTagValidator(myCurrentLexer);
if (!xmlTagValidator.validate()) {
xmlSteps = xmlTagValidator.step;
}
myCurrentLexer = myXmlLexer;
myXmlState = 0;
myCurrentLexer.start(getBufferSequence(), start, myBufferEnd, 0);
myLayeredTagStack.push(new Stack<>());
myLayeredTagStack.peek().push(new MyOpenXmlTag());
myTokenType = myCurrentLexer.getTokenType();
locateTextRange();
}
else if ((/*type == XML_ATTRIBUTE_VALUE_TOKEN || */
type == ScalaXmlTokenTypes.XML_DATA_CHARACTERS()) && //todo: Dafuq???
// in xmlLexer injection start `{` is represented by XML_DATA_CHARACTERS
// (<ul>{ {<li></li>} }</ul>).toString == <ul><li></li></ul>
// (<ul>{{<li></li>}}</ul>).toString == <ul>{<li></li>}</ul>
startsWith(tokenText, "{") &&
!startsWith(tokenText, "{{") &&
!inCdata
) {
myXmlState = myCurrentLexer.getState();
myCurrentLexer = myScalaPlainLexer;
myCurrentLexer.start(getBufferSequence(), start, myBufferEnd, 0);
locateTextRange();
myBraceStack.push(1);
myTokenType = ScalaTokenTypesEx.SCALA_IN_XML_INJECTION_START;
}
else if (type == ScalaTokenTypes.tRBRACE) {
int currentLayer = myBraceStack.popInt();
if (currentLayer == 1) {
locateTextRange();
myCurrentLexer = myXmlLexer;
myXmlLexer.start(getBufferSequence(), start + 1, myBufferEnd, myXmlState);
myTokenType = ScalaTokenTypesEx.SCALA_IN_XML_INJECTION_END;
} else {
myBraceStack.push(--currentLayer);
}
}
else if (type == ScalaTokenTypes.tLBRACE) {
int currentLayer = myBraceStack.popInt();
myBraceStack.push(++currentLayer);
}
else if ((ScalaXmlTokenTypes.XML_START_TAG_START() == type ||
ScalaXmlTokenTypes.XML_COMMENT_START() == type ||
ScalaXmlTokenTypes.XML_CDATA_START() == type ||
ScalaXmlTokenTypes.XML_PI_START() == type) &&
!myLayeredTagStack.isEmpty()
) {
if (type == ScalaXmlTokenTypes.XML_CDATA_START()) {
inCdata = true;
}
myLayeredTagStack.peek().push(new MyOpenXmlTag());
}
else if (ScalaXmlTokenTypes.XML_EMPTY_ELEMENT_END() == type &&
!myLayeredTagStack.isEmpty() &&
!myLayeredTagStack.peek().isEmpty() &&
myLayeredTagStack.peek().peek().state == TAG_STATE.UNDEFINED) {
myLayeredTagStack.peek().pop();
if (myLayeredTagStack.peek().isEmpty() && checkNotNextXmlBegin(myCurrentLexer)) {
myLayeredTagStack.pop();
locateTextRange();
myTokenType = ScalaXmlTokenTypes.XML_EMPTY_ELEMENT_END();
startScalaPlainLexer(start + 2);
return LocateXmlTokenResult.STARTED_SCALA_PLAIN_LEXER;
}
}
else if (ScalaXmlTokenTypes.XML_TAG_END() == type &&
!myLayeredTagStack.isEmpty() &&
!myLayeredTagStack.peek().isEmpty()
) {
MyOpenXmlTag tag = myLayeredTagStack.peek().peek();
if (tag.state == TAG_STATE.UNDEFINED) {
tag.state = TAG_STATE.NONEMPTY;
}
else if (tag.state == TAG_STATE.NONEMPTY) {
myLayeredTagStack.peek().pop();
}
if (myLayeredTagStack.peek().isEmpty() && checkNotNextXmlBegin(myCurrentLexer)) {
myLayeredTagStack.pop();
locateTextRange();
myTokenType = ScalaXmlTokenTypes.XML_TAG_END();
startScalaPlainLexer(start + 1);
return LocateXmlTokenResult.STARTED_SCALA_PLAIN_LEXER;
}
}
else if (ScalaXmlTokenTypes.XML_PI_END() == type &&
!myLayeredTagStack.isEmpty() &&
!myLayeredTagStack.peek().isEmpty() &&
myLayeredTagStack.peek().peek().state == TAG_STATE.UNDEFINED
) {
myLayeredTagStack.peek().pop();
if (myLayeredTagStack.peek().isEmpty() && checkNotNextXmlBegin(myCurrentLexer)) {
myLayeredTagStack.pop();
locateTextRange();
myTokenType = ScalaXmlTokenTypes.XML_PI_END();
startScalaPlainLexer(start + 2);
return LocateXmlTokenResult.STARTED_SCALA_PLAIN_LEXER;
}
}
else if (ScalaXmlTokenTypes.XML_COMMENT_END() == type &&
!myLayeredTagStack.isEmpty() &&
!myLayeredTagStack.peek().isEmpty() &&
myLayeredTagStack.peek().peek().state == TAG_STATE.UNDEFINED
) {
myLayeredTagStack.peek().pop();
if (myLayeredTagStack.peek().isEmpty() && checkNotNextXmlBegin(myCurrentLexer)) {
myLayeredTagStack.pop();
locateTextRange();
myTokenType = ScalaXmlTokenTypes.XML_COMMENT_END();
startScalaPlainLexer(start + 3);
return LocateXmlTokenResult.STARTED_SCALA_PLAIN_LEXER;
}
}
else if (ScalaXmlTokenTypes.XML_CDATA_END() == type &&
!myLayeredTagStack.isEmpty() &&
!myLayeredTagStack.peek().isEmpty() &&
myLayeredTagStack.peek().peek().state == TAG_STATE.UNDEFINED
) {
inCdata = false;
myLayeredTagStack.peek().pop();
if (myLayeredTagStack.peek().isEmpty() && checkNotNextXmlBegin(myCurrentLexer)) {
myLayeredTagStack.pop();
locateTextRange();
myTokenType = ScalaXmlTokenTypes.XML_CDATA_END();
startScalaPlainLexer(start + 3);
return LocateXmlTokenResult.STARTED_SCALA_PLAIN_LEXER;
}
}
else if (type == ScalaXmlTokenTypes.XML_DATA_CHARACTERS() &&
CharArrayUtil.indexOf(tokenText, "{", 0) != -1 && !inCdata
) {
int scalaToken = CharArrayUtil.indexOf(tokenText, "{", 0);
while (scalaToken != -1 && scalaToken + 1 < tokenText.length() && tokenText.charAt(scalaToken + 1) == '{')
scalaToken = CharArrayUtil.indexOf(tokenText, "{", scalaToken + 2);
if (scalaToken != -1) {
myTokenType = ScalaXmlTokenTypes.XML_DATA_CHARACTERS();
myTokenStart = myCurrentLexer.getTokenStart();
myTokenEnd = myTokenStart + scalaToken;
myCurrentLexer.start(getBufferSequence(), myTokenEnd, myBufferEnd, myCurrentLexer.getState());
}
}
return LocateXmlTokenResult.ADVANCE;
}