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]
}