src/language/providers/closeElementSlash.ts (158 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import * as vscode from 'vscode' import { checkMissingCloseTag } from './closeUtils' import { insertSnippet, checkBraceOpen, isInXPath, isNotTriggerChar, getNsPrefix, getItemPrefix, getItemsOnLineCount, cursorWithinBraces, cursorWithinQuotes, cursorAfterEquals, } from './utils' export function getCloseElementSlashProvider() { return vscode.languages.registerCompletionItemProvider( 'dfdl', { async provideCompletionItems( document: vscode.TextDocument, position: vscode.Position ) { let backpos = new vscode.Position(position.line, position.character - 1) const nsPrefix = getNsPrefix(document, position) const triggerText = document .lineAt(position) .text.substring(0, position.character) let nearestTagNotClosed = checkMissingCloseTag( document, position, nsPrefix ) const itemsOnLine = getItemsOnLineCount(triggerText) const triggerChar = '/' if ( checkBraceOpen(document, position) || cursorWithinBraces(document, position) || cursorWithinQuotes(document, position) || cursorAfterEquals(document, position) || isInXPath(document, position) || isNotTriggerChar(document, position, triggerChar) ) { return undefined } if (!(nearestTagNotClosed == 'none')) { let range = new vscode.Range(backpos, position) await vscode.window.activeTextEditor?.edit((editBuilder) => { editBuilder.replace(range, '') }) } if (triggerText.endsWith('/')) { checkItemsOnLine( document, position, itemsOnLine, nearestTagNotClosed, backpos, nsPrefix, triggerText ) } //return undefined }, }, '/' // triggered whenever a '/' is typed ) } export function getTDMLCloseElementSlashProvider() { return vscode.languages.registerCompletionItemProvider( 'tdml', { async provideCompletionItems( document: vscode.TextDocument, position: vscode.Position ) { let backpos = position.with(position.line, position.character - 1) const nsPrefix = getNsPrefix(document, position) const triggerText = document .lineAt(position) .text.substring(0, position.character) let nearestTagNotClosed = checkMissingCloseTag( document, position, nsPrefix ) const itemsOnLine = getItemsOnLineCount(triggerText) if ( checkBraceOpen(document, position) || cursorWithinBraces(document, position) || cursorWithinQuotes(document, position) || cursorAfterEquals(document, position) || isInXPath(document, position) ) { return undefined } if (triggerText.endsWith('/')) { checkItemsOnLine( document, position, itemsOnLine, nearestTagNotClosed, backpos, nsPrefix, triggerText ) } return undefined }, }, '/' // triggered whenever a '/' is typed ) } function checkItemsOnLine( document: vscode.TextDocument, position: vscode.Position, itemsOnLine: number, nearestTagNotClosed: string, backpos: vscode.Position, nsPrefix: string, triggerText: string ) { nsPrefix = getItemPrefix(nearestTagNotClosed, nsPrefix) if ( !(nearestTagNotClosed == 'none') && (itemsOnLine == 1 || itemsOnLine == 0) ) { if ( nearestTagNotClosed.includes('defineVariable') || nearestTagNotClosed.includes('setVariable') ) { insertSnippet('/>\n', backpos) } else { insertSnippet('/>$0', backpos) } } if (itemsOnLine > 1) { if ( triggerText.endsWith('/') && triggerText.includes('<' + nsPrefix + nearestTagNotClosed) ) { let tagPos = triggerText.lastIndexOf('<' + nsPrefix + nearestTagNotClosed) let tagEndPos = triggerText.indexOf('>', tagPos) if ( tagPos != -1 && !triggerText.substring(tagEndPos - 1, 2).includes('/>') && triggerText .substring(backpos.character - 1, backpos.character) .includes('>') && !triggerText .substring(tagEndPos) .includes('</' + nsPrefix + nearestTagNotClosed) ) { insertSnippet('</' + nsPrefix + nearestTagNotClosed + '>$0', backpos) } else { insertSnippet('/>$0', backpos) } } } }