void () { assert token() == XmlTokenType.XML_START_TAG_START : "Tag start expected"; String originalTagName; PsiBuilder.Marker xmlText = null; while (shouldContinueMainLoop() && shouldContinueParsingTag()) { final IElementType tt = token(); if (tt == XmlTokenType.XML_START_TAG_START) { xmlText = terminateText(xmlText); final PsiBuilder.Marker tagStart = mark(); // Start tag header advance(); originalTagName = parseOpenTagName(); HtmlTagInfo info = createHtmlTagInfo(originalTagName, tagStart); while (openingTagAutoClosesTagInStack(info)) { completeTopItemBefore(tagStart); } pushItemToStack(info); parseTagHeader(info.getNormalizedName()); if (token() == XmlTokenType.XML_EMPTY_ELEMENT_END) { advance(); doneTag(); continue; } if (token() == XmlTokenType.XML_TAG_END) { advance(); } else { error(XmlPsiBundle.message("xml.parsing.tag.start.is.not.closed")); doneTag(); continue; } if (isSingleTag(info)) { final PsiBuilder.Marker footer = mark(); while (token() == XmlTokenType.XML_REAL_WHITE_SPACE) { advance(); } if (token() == XmlTokenType.XML_END_TAG_START) { advance(); if (token() == XmlTokenType.XML_NAME) { if (info.getNormalizedName().equalsIgnoreCase(myBuilder.getTokenText())) { advance(); footer.drop(); if (token() == XmlTokenType.XML_TAG_END) { advance(); } doneTag(); continue; } } } footer.rollbackTo(); doneTag(); } } else if (tt == XmlTokenType.XML_PI_START) { xmlText = terminateText(xmlText); parseProcessingInstruction(); } else if (tt == XmlTokenType.XML_ENTITY_REF_TOKEN || tt == XmlTokenType.XML_CHAR_ENTITY_REF) { xmlText = startText(xmlText); parseReference(); } else if (tt == XmlTokenType.XML_CDATA_START) { xmlText = startText(xmlText); parseCData(); } else if (tt == XmlTokenType.XML_COMMENT_START) { xmlText = startText(xmlText); parseComment(); } else if (tt == XmlTokenType.XML_BAD_CHARACTER) { xmlText = startText(xmlText); final PsiBuilder.Marker error = mark(); advance(); error.error(XmlPsiBundle.message("xml.parsing.unescaped.ampersand.or.nonterminated.character.entity.reference")); } else if (tt instanceof ICustomParsingType || tt instanceof ILazyParseableElementType) { xmlText = terminateText(xmlText); maybeRemapCurrentToken(tt); advance(); } else if (token() == XmlTokenType.XML_END_TAG_START) { xmlText = terminateText(xmlText); final PsiBuilder.Marker footer = mark(); advance(); String endTagName = parseEndTagName(); if (endTagName != null) { endTagName = normalizeTagName(endTagName); final var itemOnStack = !myItemsStack.isEmpty() ? myItemsStack.peek() : null; if ((itemOnStack instanceof HtmlTagInfo tagOnStack && !tagOnStack.getNormalizedName().equals(endTagName) && !StringUtil.toLowerCase(endTagName).endsWith(COMPLETION_NAME)) || !(itemOnStack instanceof HtmlTagInfo) ) { if (itemOnStack instanceof HtmlTagInfo tagOnStack && isTagFurtherInStack(endTagName)) { footer.rollbackTo(); if (!canClosingTagAutoClose(tagOnStack, endTagName)) { error(XmlPsiBundle.message("xml.parsing.named.element.is.not.closed", tagOnStack.getOriginalName())); } doneTag(); } else { if (token() == XmlTokenType.XML_TAG_END) advance(); footer.error(XmlPsiBundle.message("xml.parsing.closing.tag.matches.nothing")); } continue; } while (token() != XmlTokenType.XML_TAG_END && token() != XmlTokenType.XML_START_TAG_START && token() != XmlTokenType.XML_END_TAG_START && !eof()) { error(XmlPsiBundle.message("xml.parsing.unexpected.token")); advance(); } } else { error(XmlPsiBundle.message("xml.parsing.closing.tag.name.missing")); } footer.drop(); if (token() == XmlTokenType.XML_TAG_END) { advance(); } else { error(XmlPsiBundle.message("xml.parsing.closing.tag.is.not.done")); } if (hasTags()) { doneTag(); } } else if ((token() == XmlTokenType.XML_REAL_WHITE_SPACE || token() == XmlTokenType.XML_DATA_CHARACTERS) && stackSize() == 0) { xmlText = terminateText(xmlText); advance(); } else if (hasCustomTagContent()) { xmlText = parseCustomTagContent(xmlText); } else { xmlText = startText(xmlText); advance(); } } terminateText(xmlText); }