export function getCloseTag()

in src/language/providers/closeUtils.ts [92:240]


export function getCloseTag(
  document: vscode.TextDocument,
  position: vscode.Position,
  nsPrefix: string,
  tag: string,
  startLine: number,
  startPos: number
): [string, number, number] {
  let lineNum = startLine
  let tagOpen = startPos
  const triggerLine = position.line
  const triggerPos = position.character
  const triggerText = document.lineAt(startLine).text
  const itemsOnLine = getItemsOnLineCount(document.lineAt(lineNum).text)
  let endPos = triggerText.lastIndexOf('>')
  nsPrefix = getItemPrefix(tag, nsPrefix)

  if (itemsOnLine === 1) {
    if (cursorInsideCloseTag(document, position))
      return ['none', lineNum, startPos]
  }

  if (itemsOnLine > 1 && startPos < endPos) {
    while (tagOpen > -1 && tagOpen <= triggerPos) {
      tagOpen = triggerText.indexOf('<', tagOpen)
      let tagClose = triggerText.indexOf('>', tagOpen)
      let tagPart = triggerText.substring(tagOpen, tagClose)

      if (
        tagPart.includes(tag) &&
        (tagPart.includes('</') || tagPart.includes('/>'))
      ) {
        return [tag, startLine, tagOpen]
      }

      tagOpen = tagClose + 1
    }
  } else {
    let nestedTagCount = 0
    let endPos = triggerText.indexOf('>', startPos)

    if (triggerText.includes('?xml version')) {
      return [tag, 0, 0]
    }

    if (
      (triggerText.includes('</') || triggerText.includes('/>')) &&
      triggerText.includes(tag) &&
      endPos > -1 &&
      itemsOnLine < 2
    ) {
      return [tag, startLine, startPos]
    }

    while (lineNum > -1 && lineNum < document.lineCount) {
      let currentText = document.lineAt(lineNum).text
      let isMultiLineTag = false

      //skip any comment lines
      if (currentText.includes('<!--')) {
        while (!currentText.includes('-->')) {
          currentText = document.lineAt(++lineNum).text
        }
        currentText = document.lineAt(++lineNum).text
      }

      startPos = currentText.indexOf('<')

      if (getItemsOnLineCount(currentText) < 2) {
        //skip lines until the close tag for this item
        if (
          currentText.includes('<' + nsPrefix + tag) &&
          currentText.endsWith('>')
        ) {
          //skipping to closing tag
          while (!currentText.includes('</' + nsPrefix + tag)) {
            currentText = document.lineAt(++lineNum).text

            //If currentText is multi tag line skip to next line
            if (getItemsOnLineCount(currentText) > 1) {
              currentText = document.lineAt(++lineNum).text
            }

            if (currentText.includes('<' + nsPrefix + tag)) {
              ++nestedTagCount
              while (!currentText.includes('>')) {
                currentText = document.lineAt(++lineNum).text
              }
              if (currentText.includes('/>')) {
                --nestedTagCount
              }
            }

            //if currentText is a closing tag
            if (
              currentText.includes('</' + nsPrefix + tag) &&
              nestedTagCount > 0
            ) {
              --nestedTagCount
              currentText = ''
            }
          }
        }

        //if end tag symbol is on a different line
        if (
          currentText.includes('<' + nsPrefix + tag) &&
          !currentText.includes('>')
        ) {
          isMultiLineTag = true

          //skip to the end tag symbol
          while (!currentText.includes('>')) {
            currentText = document.lineAt(++lineNum).text
          }

          //if the tag isn't self closing, skip to the closing tag
          if (!currentText.includes('/>')) {
            while (!currentText.includes('</' + nsPrefix + tag)) {
              currentText = document.lineAt(++lineNum).text
            }
          }
        }

        if (
          (currentText.includes('</' + nsPrefix + tag) &&
            nestedTagCount === 0) ||
          (currentText.includes('/>') && isMultiLineTag)
        ) {
          if (isMultiLineTag) {
            startPos = triggerPos
          }

          //if the cursor is after the closing tag
          if (
            lineNum == triggerLine &&
            currentText.indexOf('>', triggerPos) === -1
          ) {
            return ['none', lineNum, startPos]
          }

          return [tag, lineNum, startPos]
        }
      }
      ++lineNum
    }
  }
  return ['none', 0, 0]
}