Skip to content

Commit

Permalink
Fixes problems with space and slash truncating attribute values
Browse files Browse the repository at this point in the history
without default values when typng a space or slash in the quoted
text
Fixes a problem where typing a slash almost anywhere inserts '/>'
a self closing tag
Prevents hover popups for non-attribute items
Fixes intellisense suggesting incorrect attributes for elements
that spread across multiple lines

closes #1065
  • Loading branch information
rthomas320 committed Oct 3, 2024
1 parent 817221d commit c262b6b
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 112 deletions.
20 changes: 20 additions & 0 deletions src/language/providers/attributeCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,26 @@ function checkNearestOpenItem(
spacingChar,
afterChar
)
case 'include':
return getCompletionItems(
['schemaLocation'],
'',
'',
nsPrefix,
'',
spacingChar,
afterChar
)
case 'import':
return getCompletionItems(
['schemaLocation', 'namespace'],
'',
'',
nsPrefix,
'',
spacingChar,
afterChar
)
case 'assert':
return getCompletionItems(
['testKind', 'test', 'testPattern', 'message', 'failureType'],
Expand Down
12 changes: 3 additions & 9 deletions src/language/providers/attributeValueCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,19 @@ export function getAttributeValueCompletionProvider() {
position
)

if (attributeName !== 'none') {
if (attributeName !== 'none' && !attributeName.includes('xmlns:')) {
let replaceValue = ''
if (startPos === endPos) {
replaceValue = ' '
}

if (
attributeName.includes(':') &&
!attributeName.includes('xmlns:')
) {
if (attributeName.includes(':')) {
attributeName = attributeName.substring(
attributeName.indexOf(':') + 1
)
}

if (
noChoiceAttributes.includes(attributeName) ||
attributeName.includes('xmlns:')
) {
if (noChoiceAttributes.includes(attributeName)) {
return undefined
}

Expand Down
19 changes: 15 additions & 4 deletions src/language/providers/closeElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getXsdNsPrefix,
insertSnippet,
isInXPath,
isNotTriggerChar,
getItemsOnLineCount,
getItemPrefix,
} from './utils'
Expand All @@ -39,12 +40,14 @@ export function getCloseElementProvider() {
document: vscode.TextDocument,
position: vscode.Position
) {
let triggerChar = '>'
if (
checkBraceOpen(document, position) ||
cursorWithinBraces(document, position) ||
cursorWithinQuotes(document, position) ||
cursorAfterEquals(document, position) ||
isInXPath(document, position)
isInXPath(document, position) ||
isNotTriggerChar(document, position, triggerChar)
) {
return undefined
}
Expand Down Expand Up @@ -184,7 +187,7 @@ export function getTDMLCloseElementProvider() {
backpos3
)
}
return undefined
//return undefined
},
},
'>' // triggered whenever a '>' is typed
Expand All @@ -202,7 +205,11 @@ function checkItemsOnLine(
backpos: vscode.Position,
backpos3: vscode.Position
) {
if (itemsOnLine == 0 && !triggerText.includes('</')) {
if (
itemsOnLine == 0 &&
!triggerText.includes('</') &&
!triggerText.includes('/>')
) {
if (triggerText.trim() === '>') {
insertSnippet('</' + nsPrefix + nearestTagNotClosed + '>', backpos)
} else {
Expand Down Expand Up @@ -237,7 +244,11 @@ function checkItemsOnLine(
}
}

if (itemsOnLine === 1 && !triggerText.includes('</')) {
if (
itemsOnLine === 1 &&
!triggerText.includes('</') &&
!triggerText.includes('/>')
) {
checkNearestTagNotClosed(
document,
position,
Expand Down
42 changes: 22 additions & 20 deletions src/language/providers/closeElementSlash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
insertSnippet,
checkBraceOpen,
isInXPath,
isNotTriggerChar,
getXsdNsPrefix,
getItemPrefix,
getItemsOnLineCount,
Expand All @@ -47,28 +48,28 @@ export function getCloseElementSlashProvider() {
position,
nsPrefix
)
if (nearestTagNotClosed === 'none') {
return undefined
}
const itemsOnLine = getItemsOnLineCount(triggerText)

const triggerChar = '/'
if (
checkBraceOpen(document, position) ||
cursorWithinBraces(document, position) ||
cursorWithinQuotes(document, position) ||
cursorAfterEquals(document, position) ||
isInXPath(document, position)
isInXPath(document, position) ||
isNotTriggerChar(document, position, triggerChar)
) {
return undefined
}

if (triggerText.endsWith('/')) {
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,
Expand All @@ -80,7 +81,7 @@ export function getCloseElementSlashProvider() {
)
}

return undefined
//return undefined
},
},
'/'
Expand Down Expand Up @@ -119,12 +120,6 @@ export function getTDMLCloseElementSlashProvider() {
}

if (triggerText.endsWith('/')) {
let range = new vscode.Range(backpos, position)

await vscode.window.activeTextEditor?.edit((editBuilder) => {
editBuilder.replace(range, '')
})

checkItemsOnLine(
document,
position,
Expand Down Expand Up @@ -155,19 +150,22 @@ function checkItemsOnLine(
) {
nsPrefix = getItemPrefix(nearestTagNotClosed, nsPrefix)

if (itemsOnLine == 1 || itemsOnLine == 0) {
insertSnippet('/>$0', backpos)
if (
!(nearestTagNotClosed == 'none') &&
(itemsOnLine == 1 || itemsOnLine == 0)
) {
// let range = new vscode.Range(backpos, position)

// await vscode.window.activeTextEditor?.edit((editBuilder) => {
// editBuilder.replace(range, '')
// })
if (
nearestTagNotClosed.includes('defineVariable') ||
nearestTagNotClosed.includes('setVariable')
) {
let range = new vscode.Range(backpos, position)
vscode.window.activeTextEditor?.edit((editBuilder) => {
editBuilder.replace(range, '')
})

insertSnippet('/>\n', backpos)
} else {
insertSnippet('/>$0', backpos)
}
}

Expand All @@ -178,6 +176,10 @@ function checkItemsOnLine(
) {
let tagPos = triggerText.lastIndexOf('<' + nsPrefix + nearestTagNotClosed)
let tagEndPos = triggerText.indexOf('>', tagPos)
// let range = new vscode.Range(backpos, position)
// await vscode.window.activeTextEditor?.edit((editBuilder) => {
// editBuilder.replace(range, '')
// })

if (
tagPos != -1 &&
Expand Down
1 change: 1 addition & 0 deletions src/language/providers/closeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export function getItemsForLineLT2(
testLine = lineBefore
while (!testText.includes('>')) {
testText = document.lineAt(++testLine).text
if (testText.indexOf('<') > -1) [openTagArray.push(testLine)]
}
}

Expand Down
125 changes: 69 additions & 56 deletions src/language/providers/elementCompletion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
checkBraceOpen,
getXsdNsPrefix,
isInXPath,
isTagEndTrigger,
nearestOpen,
createCompletionItem,
getCommonItems,
Expand All @@ -33,68 +34,74 @@ import {
import { elementCompletion } from './intellisense/elementItems'

export function getElementCompletionProvider(dfdlFormatString: string) {
return vscode.languages.registerCompletionItemProvider('dfdl', {
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
context: vscode.CompletionContext
) {
if (
checkBraceOpen(document, position) ||
cursorWithinBraces(document, position) ||
cursorWithinQuotes(document, position) ||
cursorAfterEquals(document, position) ||
isInXPath(document, position)
return vscode.languages.registerCompletionItemProvider(
'dfdl',
{
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
context: vscode.CompletionContext
) {
return undefined
}

let nsPrefix = getXsdNsPrefix(document, position)
let [triggerLine, triggerPos] = [position.line, position.character]
let triggerText = document.lineAt(triggerLine).text
let itemsOnLine = getItemsOnLineCount(triggerText)
let nearestOpenItem = nearestOpen(document, position)
let lastCloseSymbol = triggerText.lastIndexOf('>')
let firstOpenSymbol = triggerText.indexOf('<')

let missingCloseTag = checkMissingCloseTag(document, position, nsPrefix)

if (nearestOpenItem.includes('none')) {
if (missingCloseTag !== 'none') {
return undefined
}
if (
missingCloseTag === 'none' &&
itemsOnLine > 1 &&
(triggerPos === lastCloseSymbol + 1 || triggerPos === firstOpenSymbol)
!checkBraceOpen(document, position) &&
!cursorWithinBraces(document, position) &&
!cursorWithinQuotes(document, position) &&
!cursorAfterEquals(document, position) &&
!isInXPath(document, position) &&
!isTagEndTrigger(document, position)
) {
return undefined
}

let definedVariables = getDefinedVariables(document)
let nsPrefix = getXsdNsPrefix(document, position)
let [triggerLine, triggerPos] = [position.line, position.character]
let triggerText = document.lineAt(triggerLine).text
let itemsOnLine = getItemsOnLineCount(triggerText)
let nearestOpenItem = nearestOpen(document, position)
let lastCloseSymbol = triggerText.lastIndexOf('>')
let firstOpenSymbol = triggerText.indexOf('<')

let missingCloseTag = checkMissingCloseTag(
document,
position,
nsPrefix
)

let [tagNearestTrigger, tagPosition] = getTagNearestTrigger(
document,
position,
triggerText,
triggerLine,
triggerPos,
itemsOnLine,
nsPrefix
)
if (!nearestOpenItem.includes('none') && missingCloseTag == 'none') {
return undefined
}
if (
missingCloseTag === 'none' &&
itemsOnLine > 1 &&
(triggerPos === lastCloseSymbol + 1 ||
triggerPos === firstOpenSymbol)
) {
return undefined
}

let definedVariables = getDefinedVariables(document)

let [tagNearestTrigger, tagPosition] = getTagNearestTrigger(
document,
position,
triggerText,
triggerLine,
triggerPos,
itemsOnLine,
nsPrefix
)

return nearestOpenTagChildElements(
document,
position,
tagNearestTrigger,
tagPosition,
definedVariables,
nsPrefix
)
}
return nearestOpenTagChildElements(
document,
position,
tagNearestTrigger,
tagPosition,
definedVariables,
nsPrefix
)
}
},
},
})
'\n'
)
}

export function getTDMLElementCompletionProvider(tdmlFormatString: string) {
Expand Down Expand Up @@ -386,6 +393,10 @@ function nearestOpenTagChildElements(
return getElementCompletionItems(['dfdl:escapeScheme'], '', '', nsPrefix)
case 'format':
return getElementCompletionItems(['dfdl:property'], '', '', nsPrefix)
case 'include':
return getElementCompletionItems([''], '', '', nsPrefix)
case 'import':
return getElementCompletionItems([''], '', '', nsPrefix)
case 'schema':
return getElementCompletionItems(
[
Expand All @@ -396,6 +407,8 @@ function nearestOpenTagChildElements(
'complexType',
'simpleType',
'annotation',
'include',
'import',
],
'',
'',
Expand Down
4 changes: 4 additions & 0 deletions src/language/providers/intellisense/attributeHoverItems.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,10 @@ export function attributeHoverValues(attributeName: string): string {
return 'Defines text for use in an error message'
case 'failureType':
return 'Specifies the type of failure that occurs when the dfdl:assert is unsuccessful'
case 'schemaLocation':
return 'Specifies the location of the schema'
case 'namespace':
return 'User defined identifier for the namespace defined by schemaLocation value'
default:
return 'No definition available'
}
Expand Down
Loading

0 comments on commit c262b6b

Please sign in to comment.