override fun parseTag()

in flex/src/com/intellij/lang/actionscript/parsing/ActionScriptXmlTokensParser.kt [25:168]


  override fun parseTag(names: Stack<String>): Boolean {
    val tokenType = builder.tokenType
    assert(JSTokenTypes.XML_START_TAG_START === tokenType || JSTokenTypes.XML_START_TAG_LIST === tokenType)

    val marker = builder.mark()
    builder.advanceLexer()
    val name: String?
    if (builder.tokenType === JSTokenTypes.XML_LBRACE) {
      val nameBuilder = StringBuilder()
      parseXmlJsScript(nameBuilder)
      name = nameBuilder.toString()
    }
    else {
      name = builder.tokenText
    }
    var seenEnd = JSTokenTypes.XML_START_TAG_LIST === tokenType
    names.push(name)
    var hasErrors = false
    try {
      var currentTokenType = builder.tokenType
      while (currentTokenType != null
      ) {
        if (!JSElementTypes.XML_TOKENS.contains(currentTokenType)
            && currentTokenType !== JSTokenTypes.XML_LBRACE
        ) {
          if (!seenEnd) {
            builder.error(XmlParserBundle.message("xml.parsing.tag.start.is.not.closed"))
            return false
          }
          val errorMarker = builder.mark()
          builder.advanceLexer()
          errorMarker.error(JavaScriptParserBundle.message("javascript.parser.message.expected.xml.element"))
          currentTokenType = builder.tokenType
          continue
        }

        if (currentTokenType === JSTokenTypes.XML_START_TAG_START ||
            currentTokenType === JSTokenTypes.XML_START_TAG_LIST
        ) {
          parseTag(names)
          currentTokenType = builder.tokenType
          continue
        }
        else if (currentTokenType === JSTokenTypes.XML_EMPTY_TAG_END ||
                 currentTokenType === JSTokenTypes.XML_END_TAG_LIST
        ) {
          builder.advanceLexer()
          return !hasErrors
        }
        else if (currentTokenType === JSTokenTypes.XML_END_TAG_START) {
          if (!seenEnd) {
            builder.error(XmlParserBundle.message("xml.parsing.tag.start.is.not.closed"))
            return false
          }

          val endTagStart = builder.mark()
          builder.advanceLexer()
          val type = builder.tokenType
          if (type === XmlTokenType.XML_TAG_NAME
              || type === JSTokenTypes.XML_LBRACE) {
            val endName: String?
            if (type === JSTokenTypes.XML_LBRACE) {
              val nameBuilder = StringBuilder()
              parseXmlJsScript(nameBuilder)
              endName = nameBuilder.toString()
            }
            else {
              endName = builder.tokenText
            }
            if (!StringUtil.equals(name, endName)
                && (endName == null || !endName.endsWith(CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED))
            ) {
              if (names.contains(endName)) {
                endTagStart.rollbackTo()
                builder.error(XmlParserBundle.message("xml.parsing.named.element.is.not.closed", name))
                return !hasErrors
              }
              else {
                builder.error(XmlParserBundle.message("xml.parsing.closing.tag.matches.nothing"))
                hasErrors = true
              }
            }
            if (type !== JSTokenTypes.XML_LBRACE) {
              builder.advanceLexer()
            }
          }
          else if (JSTokenTypes.XML_START_TAG_LIST !== tokenType) {
            builder.error(XmlParserBundle.message("xml.parsing.closing.tag.name.missing"))
            hasErrors = true
          }
          if (builder.tokenType !== XmlTokenType.XML_TAG_END) {
            builder.error(XmlParserBundle.message("xml.parsing.closing.tag.is.not.done"))
            hasErrors = true
          }
          else {
            builder.advanceLexer()
          }

          endTagStart.drop()
          return !hasErrors
        }
        else if (currentTokenType === JSTokenTypes.XML_NAME) {
          parseAttribute()
          currentTokenType = builder.tokenType
          continue
        }
        else if (currentTokenType === JSTokenTypes.XML_TAG_CONTENT) {
          val xmlTextMarker = builder.mark()
          builder.advanceLexer()
          xmlTextMarker.done(JSElementTypes.XML_TEXT)

          currentTokenType = builder.tokenType
          continue
        }

        if (currentTokenType === JSTokenTypes.XML_TAG_END) {
          seenEnd = true
        }

        if (currentTokenType === JSTokenTypes.XML_LBRACE) {
          parseXmlJsScript(null)
        }
        else {
          if (currentTokenType === JSTokenTypes.XML_RBRACE) {
            builder.error(JavaScriptParserBundle.message("javascript.parser.message.unexpected.token", builder.tokenText))
          }
          builder.advanceLexer()
        }

        if (currentTokenType !== JSTokenTypes.XML_LBRACE
            && builder.tokenType === JSTokenTypes.XML_ATTR_EQUAL) {
          builder.error(JavaScriptParserBundle.message("javascript.parser.message.missing.attribute.name"))
          hasErrors = true
        }
        currentTokenType = builder.tokenType
      }
      return !hasErrors
    }
    finally {
      names.pop()
      marker.done(xmlLiteralExpression)
      marker.setCustomEdgeTokenBinders(null, INCOMPLETE_TAG_WHITESPACE_BINDER)
    }
  }