This is an automated email from the ASF dual-hosted git repository.
rthomas320 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil-vscode.git
The following commit(s) were added to refs/heads/main by this push:
new 9be74dd handle name and ref attributes consistently modified
suggestions so that newVaribleInstance is not available for group element with
an name attribute added missing ref attribute to xml tags that require it bug
fix for intellisense deleting attributes when an attribute value ends in an
equal sign fixed an intellisense logic flaw that presented element suggestions
instead of attribute suggestion in some instances
9be74dd is described below
commit 9be74dd9f5042536579d9444295b31eeec783c87
Author: rthomas320 <[email protected]>
AuthorDate: Tue Jul 15 10:24:57 2025 -0400
handle name and ref attributes consistently
modified suggestions so that newVaribleInstance is not available for
group element with an name attribute
added missing ref attribute to xml tags that require it
bug fix for intellisense deleting attributes when an attribute value
ends in an equal sign
fixed an intellisense logic flaw that presented element suggestions
instead of attribute suggestion in some instances
closes #1082
closes #1306
closes #1307
closes #1318
closes #1326
---
src/language/providers/attributeCompletion.ts | 17 +-
src/language/providers/attributeValueCompletion.ts | 17 +-
src/language/providers/closeElementSlash.ts | 14 +-
src/language/providers/closeUtils.ts | 8 +
src/language/providers/elementCompletion.ts | 62 ++++--
.../providers/intellisense/elementItems.ts | 19 +-
src/language/providers/utils.ts | 228 ++++++++++++++-------
src/tests/DfdlIntellisenseTestingChecklist.md | 2 +-
src/tests/suite/language/items.test.ts | 7 +-
9 files changed, 268 insertions(+), 106 deletions(-)
diff --git a/src/language/providers/attributeCompletion.ts
b/src/language/providers/attributeCompletion.ts
index 806e102..7184bb2 100644
--- a/src/language/providers/attributeCompletion.ts
+++ b/src/language/providers/attributeCompletion.ts
@@ -74,6 +74,7 @@ function getCompletionItems(
* @param document
* @returns
*/
+
function getPotentialAttributeText(
position: vscode.Position,
document: vscode.TextDocument
@@ -83,6 +84,11 @@ function getPotentialAttributeText(
let upperLineBound: number = position.line
// Determining the lowerbound strategy: Traverse backwards line-by-line
until we encounter an opening character (<)
+
+ //handle edge case if there's an element closing on the same line or if
there is a closing tag after the cursor on the same line
+ if (lowerLineBound > 0) {
+ lowerLineBound--
+ }
while (
lowerLineBound > 0 && // Make sure we aren't going to negative line indexes
document.lineAt(lowerLineBound).text.indexOf('<') == -1 // continue going
up the document if there is no <
@@ -164,7 +170,7 @@ function prunedDuplicateAttributes(
// Traverse forward character by character to find > or <
while (
- indexUpperBound < relevantDocText.length - 1 &&
+ indexUpperBound < relevantDocText.length &&
!(
relevantDocText[indexUpperBound] == '<' ||
relevantDocText[indexUpperBound] == '>'
@@ -177,7 +183,7 @@ function prunedDuplicateAttributes(
// Force it to be closed if the current xml element isn't closed it
const fullXMLElementText =
relevantDocText[indexUpperBound - 1] != '>'
- ? `${relevantDocText.substring(indexLowerBound, indexUpperBound - 1)}>`
+ ? `${relevantDocText.substring(indexLowerBound, indexUpperBound)}>`
: relevantDocText.substring(indexLowerBound, indexUpperBound)
// Obtain attributes for the currentl XML element after attempting to parse
the whole thing as an XML element
@@ -223,6 +229,7 @@ export function getAttributeCompletionProvider() {
let nearestOpenItem = xmlItem.itemName
let itemsOnLine = getItemsOnLineCount(triggerText)
const nsPrefix = xmlItem.itemNS
+ const attributeNames = xmlItem.itemAttributes
let additionalItems = getDefinedTypes(
document,
getSchemaNsPrefix(document)
@@ -245,8 +252,10 @@ export function getAttributeCompletionProvider() {
itemsOnLine < 2
? '\t'
: ''
+
const fullAttrCompletionList = checkNearestOpenItem(
nearestOpenItem,
+ attributeNames,
triggerText,
nsPrefix,
preVal,
@@ -286,6 +295,7 @@ export function getTDMLAttributeCompletionProvider() {
let nearestOpenItem = xmlItem.itemName
let itemsOnLine = getItemsOnLineCount(triggerText)
const nsPrefix = xmlItem.itemNS
+ const attributeNames = xmlItem.itemAttributes
let additionalItems = getDefinedTypes(document, nsPrefix)
if (isInXPath(document, position)) return undefined
@@ -308,6 +318,7 @@ export function getTDMLAttributeCompletionProvider() {
return checkNearestOpenItem(
nearestOpenItem,
+ attributeNames,
triggerText,
nsPrefix,
preVal,
@@ -354,6 +365,7 @@ export function getDefinedTypes(
function checkNearestOpenItem(
nearestOpenItem: string,
+ attributeNames: string[],
triggerText: string,
nsPrefix: string,
preVal: string,
@@ -524,6 +536,7 @@ function checkNearestOpenItem(
case 'format':
return getCompletionItems(
[
+ 'ref',
'dfdl:byteOrder',
'dfdl:bitOrder',
'dfdl:binaryNumberRep',
diff --git a/src/language/providers/attributeValueCompletion.ts
b/src/language/providers/attributeValueCompletion.ts
index 076e003..4250b00 100644
--- a/src/language/providers/attributeValueCompletion.ts
+++ b/src/language/providers/attributeValueCompletion.ts
@@ -17,7 +17,12 @@
import * as vscode from 'vscode'
-import { checkBraceOpen, cursorWithinBraces, getNsPrefix } from './utils'
+import {
+ checkBraceOpen,
+ cursorWithinBraces,
+ cursorWithinQuotes,
+ getNsPrefix,
+} from './utils'
import { getDefinedTypes } from './attributeCompletion'
import {
attributeValues,
@@ -34,7 +39,8 @@ export function getAttributeValueCompletionProvider() {
) {
if (
checkBraceOpen(document, position) ||
- cursorWithinBraces(document, position)
+ cursorWithinBraces(document, position) ||
+ !cursorWithinQuotes(document, position)
) {
return undefined
}
@@ -189,10 +195,9 @@ function getAttributeDetails(
)
endPos = currentText.indexOf(quoteChar[i], currentPos + 1)
attributeStartPos = textBeforeTrigger.lastIndexOf(' ')
- attributeName = textBeforeTrigger.substring(
- attributeStartPos + 1,
- currentPos - 1
- )
+ attributeName = textBeforeTrigger
+ .substring(attributeStartPos + 1, currentPos - 1)
+ .trim()
}
}
}
diff --git a/src/language/providers/closeElementSlash.ts
b/src/language/providers/closeElementSlash.ts
index ff18b0b..c2fff16 100644
--- a/src/language/providers/closeElementSlash.ts
+++ b/src/language/providers/closeElementSlash.ts
@@ -39,8 +39,18 @@ export function getCloseElementSlashProvider() {
position: vscode.Position
) {
let backpos = new vscode.Position(position.line, position.character -
1)
- const nsPrefix = getNsPrefix(document, position)
- const triggerText = document
+ let nsPrefix = getNsPrefix(document, position)
+ let triggerText = document.lineAt(position.line).text
+ let tagPos = triggerText.lastIndexOf('<' + nsPrefix + ':')
+ triggerText.lastIndexOf(',' + nsPrefix + ':')
+ if (tagPos < 0) {
+ tagPos = triggerText.lastIndexOf('<dfdl:')
+ if (tagPos > 0) {
+ nsPrefix = 'dfdl:'
+ }
+ }
+
+ triggerText = document
.lineAt(position)
.text.substring(0, position.character)
let nearestTagNotClosed = checkMissingCloseTag(
diff --git a/src/language/providers/closeUtils.ts
b/src/language/providers/closeUtils.ts
index 3b6d285..297e1c3 100644
--- a/src/language/providers/closeUtils.ts
+++ b/src/language/providers/closeUtils.ts
@@ -34,6 +34,14 @@ export function checkMissingCloseTag(
const textBeforeTrigger = triggerText.substring(0, triggerPos)
nsPrefix = getItemPrefix(items[i], origPrefix)
+ let tagPos = triggerText.lastIndexOf('<' + nsPrefix + items[i])
+
+ if (tagPos < 0) {
+ tagPos = triggerText.lastIndexOf('<dfdl:' + items[i])
+ if (tagPos > 0) {
+ nsPrefix = 'dfdl:'
+ }
+ }
if (itemsOnLine > 1) {
if (textBeforeTrigger.lastIndexOf('<' + nsPrefix + items[i]) > -1) {
diff --git a/src/language/providers/elementCompletion.ts
b/src/language/providers/elementCompletion.ts
index 3f07999..77178da 100644
--- a/src/language/providers/elementCompletion.ts
+++ b/src/language/providers/elementCompletion.ts
@@ -27,6 +27,7 @@ import {
createCompletionItem,
getCommonItems,
nearestTag,
+ getAttributeNames,
getItemsOnLineCount,
cursorWithinBraces,
cursorWithinQuotes,
@@ -312,7 +313,17 @@ function nearestOpenTagChildElements(
iCount < 2
? new vscode.Position(tagPosition.line - 1, tagPosition.character)
: tagPosition
- let pElement = getAnnotationParent(document, newPosition, nsPrefix)
+ let [pElement, pPosition] = getAnnotationParent(
+ document,
+ newPosition,
+ nsPrefix
+ )
+ let attributeNames: string[] = getAttributeNames(
+ document,
+ pPosition,
+ nsPrefix,
+ pElement
+ )
switch (pElement) {
case 'schema':
return getElementCompletionItems(
@@ -332,7 +343,6 @@ function nearestOpenTagChildElements(
'dfdl:assert',
'dfdl:discriminator',
'dfdl:element',
- 'dfdl:setVariable',
'dfdl:property',
],
'',
@@ -344,6 +354,7 @@ function nearestOpenTagChildElements(
[
'dfdl:assert',
'dfdl:discriminator',
+ 'dfdl:setVariable',
'dfdl:newVariableInstance',
'dfdl:sequence',
],
@@ -365,18 +376,32 @@ function nearestOpenTagChildElements(
nsPrefix
)
case 'group':
- return getElementCompletionItems(
- [
- 'dfdl:assert',
- 'dfdl:group',
- 'dfdl:discriminator',
- 'dfdl:newVariableInstance',
- 'dfdl:setVariable',
- ],
- '',
- '',
- nsPrefix
- )
+ if (attributeNames.includes('ref')) {
+ return getElementCompletionItems(
+ [
+ 'dfdl:assert',
+ 'dfdl:group',
+ 'dfdl:discriminator',
+ 'dfdl:newVariableInstance',
+ 'dfdl:setVariable',
+ ],
+ '',
+ '',
+ nsPrefix
+ )
+ } else {
+ return getElementCompletionItems(
+ [
+ 'dfdl:assert',
+ 'dfdl:group',
+ 'dfdl:discriminator',
+ 'dfdl:setVariable',
+ ],
+ '',
+ '',
+ nsPrefix
+ )
+ }
case 'simpleType':
return getElementCompletionItems(
[
@@ -419,6 +444,7 @@ function nearestOpenTagChildElements(
'annotation',
'include',
'import',
+ 'defineVariable',
],
'',
'',
@@ -437,10 +463,11 @@ export function getAnnotationParent(
document: vscode.TextDocument,
tagPosition: vscode.Position,
nsPrefix: string
-): string {
+): [string, vscode.Position] {
let pElementText = document.lineAt(tagPosition.line).text
let iCount = getItemsOnLineCount(pElementText)
let pElement = ''
+ let pPosition = tagPosition
let [nElement, newPosition] = getTagNearestTrigger(
document,
tagPosition,
@@ -460,7 +487,7 @@ export function getAnnotationParent(
)
}
pElementText = document.lineAt(newPosition.line).text
- let [nElement] = getTagNearestTrigger(
+ let [nElement, nPosition] = getTagNearestTrigger(
document,
newPosition,
pElementText,
@@ -470,8 +497,9 @@ export function getAnnotationParent(
nsPrefix
)
pElement = nElement
+ pPosition = nPosition
}
- return pElement
+ return [pElement, pPosition]
}
export function getTagNearestTrigger(
diff --git a/src/language/providers/intellisense/elementItems.ts
b/src/language/providers/intellisense/elementItems.ts
index e3517c6..d364b9b 100644
--- a/src/language/providers/intellisense/elementItems.ts
+++ b/src/language/providers/intellisense/elementItems.ts
@@ -27,6 +27,11 @@ export const elementCompletion = (definedVariables,
nsPrefix) => {
item: nsPrefix + 'schema',
snippetString: '<${1|\0,xs:,xsd:|}$2' + 'schema
xmlns:xs="http://www.w3.org/2001/xmlSchema"\n\t\txmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"\n\t\txmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"\n\t\txmlns:fn="http:/www.w3.org/2005/xpath-functions"\nelementFormDefault="unqualified"$0',
},
+ {
+ item: nsPrefix + 'element',
+ snippetString: '<' + nsPrefix + 'element $1"$0',
+ markdownString: 'Defines an xs element',
+ },
{
item: nsPrefix + 'element name',
snippetString: '<' + nsPrefix + 'element name="$1"$0',
@@ -37,6 +42,11 @@ export const elementCompletion = (definedVariables,
nsPrefix) => {
snippetString: '<' + nsPrefix + 'element ref="$1"$0',
markdownString: 'Defines a reference to a declared element',
},
+ {
+ item: nsPrefix + 'group',
+ snippetString: '<' + nsPrefix + 'group "$1">\n\t$0\n</' + nsPrefix +
'group>',
+ markdownString: 'Defines a named model group to be reused later',
+ },
{
item: nsPrefix + 'group name',
snippetString: '<' + nsPrefix + 'group name = "$1">\n\t$0\n</' +
nsPrefix + 'group>',
@@ -76,7 +86,7 @@ export const elementCompletion = (definedVariables, nsPrefix)
=> {
markdownString: 'Defines a complex type definition',
},
{
- item: nsPrefix + 'complexType name=',
+ item: nsPrefix + 'complexType name',
snippetString: '<' + nsPrefix + 'complexType name="$1">\n\t$0\n</' +
nsPrefix + 'complexType>',
markdownString: 'Defines a complex type definition',
},
@@ -86,7 +96,7 @@ export const elementCompletion = (definedVariables, nsPrefix)
=> {
markdownString: 'Defines a simple type definition',
},
{
- item: nsPrefix + 'simpleType name=',
+ item: nsPrefix + 'simpleType name',
snippetString: '<' + nsPrefix + 'simpleType name="$1"$0',
markdownString: 'Defines simple type definition',
},
@@ -107,6 +117,11 @@ export const elementCompletion = (definedVariables,
nsPrefix) => {
},
{
item: 'dfdl:defineVariable',
+ snippetString: '<dfdl:defineVariable "$1"$0',
+ markdownString: 'Defines the name, type, and optionally default value
for the variable.',
+ },
+ {
+ item: 'dfdl:defineVariable name',
snippetString: '<dfdl:defineVariable name="$1"$0',
markdownString: 'Defines the name, type, and optionally default value
for the variable.',
},
diff --git a/src/language/providers/utils.ts b/src/language/providers/utils.ts
index 087e608..10e19fd 100644
--- a/src/language/providers/utils.ts
+++ b/src/language/providers/utils.ts
@@ -18,6 +18,7 @@
import * as vscode from 'vscode'
import { commonCompletion } from './intellisense/commonItems'
import { isXPath } from '../semantics/dfdlExt'
+import { xml2js } from 'xml-js'
const schemaPrefixRegEx = new RegExp('</?(|[^ ]+:)schema')
@@ -53,6 +54,7 @@ const items = [
export class XmlItem {
private _itemName: string = 'none'
private _itemNS: string = 'none'
+ private _itemAttributes: string[] = []
public get itemName() {
return this._itemName
@@ -69,6 +71,14 @@ export class XmlItem {
public set itemNS(nameSpace: string) {
this._itemNS = nameSpace
}
+
+ public set itemAttributes(attributeNames: string[]) {
+ this._itemAttributes = attributeNames
+ }
+
+ public get itemAttributes() {
+ return this._itemAttributes
+ }
}
export function getItems() {
@@ -131,7 +141,7 @@ export function nearestOpen(
const nsPrefix = getNsPrefix(document, position)
for (let i = 0; i < items.length; ++i) {
- let [isTagOpen, isDfdlNs] = checkTagOpen(
+ let [isTagOpen, isDfdlNs, attributeNames] = checkTagOpen(
document,
position,
nsPrefix,
@@ -144,6 +154,7 @@ export function nearestOpen(
xmlItem.itemNS = nsPrefix
}
xmlItem.itemName = items[i]
+ xmlItem.itemAttributes = attributeNames
return xmlItem
}
}
@@ -236,7 +247,7 @@ export function checkTagOpen(
position: vscode.Position,
nsPrefix: string,
tag: string
-): [boolean, boolean] {
+): [boolean, boolean, string[]] {
let triggerLine = position.line
let triggerText = document.lineAt(triggerLine).text
let itemsOnLine = getItemsOnLineCount(triggerText)
@@ -245,71 +256,82 @@ export function checkTagOpen(
let origTriggerLine = triggerLine
let compareText = triggerText
let compareLine = triggerLine
+ let attributeNames: string[] = []
const triggerPos = position.character
- const textBeforeTrigger = triggerText.substring(0, triggerPos)
while (itemsOnLine < 2 && !triggerText.trim().startsWith('<')) {
triggerText = document.lineAt(--triggerLine).text
}
- if (!(triggerText.endsWith('>') && triggerText.includes('<'))) {
- isMultiLineTag = true
- }
+ let tagPos = triggerText.lastIndexOf('<' + nsPrefix + tag)
- let tagPos = textBeforeTrigger.lastIndexOf('<' + nsPrefix + tag)
if (tagPos < 0) {
- tagPos = textBeforeTrigger.lastIndexOf('<dfdl:' + tag)
+ tagPos = triggerText.lastIndexOf('<dfdl:' + tag)
if (tagPos > 0) {
isDfdlPrefix = true
nsPrefix = 'dfdl:'
}
}
- const nextTagPos = triggerText.indexOf('<', tagPos + 1)
- let tagEndPos = triggerText.indexOf('>', tagPos)
- if (tagPos > -1 && itemsOnLine > 1) {
- if (
- triggerPos > tagPos &&
- ((triggerPos <= tagEndPos &&
- (nextTagPos > tagEndPos || nextTagPos === -1)) ||
- tagEndPos === -1)
- ) {
- return [true, isDfdlPrefix]
- }
+ if (
+ !(
+ triggerText.trim().startsWith('<' + nsPrefix + tag) &&
+ triggerText.endsWith('>')
+ )
+ ) {
+ isMultiLineTag = true
}
- while (compareText.trim() === '') {
- compareText = document.lineAt(--compareLine).text
- }
- tagPos = triggerText.indexOf('<' + nsPrefix + tag)
- if (tagPos < 0) {
- tagPos = textBeforeTrigger.lastIndexOf('<dfdl:' + tag)
- if (tagPos > 0) {
- isDfdlPrefix = true
- nsPrefix = 'dfdl:'
+ if (!isMultiLineTag) {
+ const nextTagPos = triggerText.indexOf('<', tagPos + 1)
+ let tagEndPos = triggerText.indexOf('>', tagPos)
+
+ if (tagPos > -1 && itemsOnLine > 1) {
+ if (
+ triggerPos > tagPos &&
+ ((triggerPos <= tagEndPos &&
+ (nextTagPos > tagEndPos || nextTagPos === -1)) ||
+ tagEndPos === -1)
+ ) {
+ attributeNames = getAttributeNames(document, position, nsPrefix, tag)
+ return [true, isDfdlPrefix, attributeNames]
+ }
}
- }
- if (itemsOnLine < 2 && tagPos > -1) {
- if (triggerText !== compareText) {
- tagEndPos = compareText.indexOf('>')
+ while (compareText.trim() === '') {
+ compareText = document.lineAt(--compareLine).text
+ }
+ tagPos = triggerText.indexOf('<' + nsPrefix + tag)
+ if (tagPos < 0) {
+ tagPos = triggerText.lastIndexOf('<dfdl:' + tag)
+ if (tagPos > 0) {
+ isDfdlPrefix = true
+ nsPrefix = 'dfdl:'
+ }
}
- if (
- (triggerPos > tagPos &&
- triggerPos <= tagEndPos &&
- triggerLine === position.line) ||
- (compareLine == position.line &&
- triggerPos <= tagEndPos &&
- triggerPos > tagPos) ||
- position.line < origTriggerLine
- ) {
- return [true, isDfdlPrefix]
+ if (itemsOnLine < 2 && tagPos > -1) {
+ if (triggerText !== compareText) {
+ tagEndPos = compareText.indexOf('>')
+ }
+
+ if (
+ (triggerPos > tagPos &&
+ triggerPos <= tagEndPos &&
+ triggerLine === position.line) ||
+ (compareLine == position.line &&
+ triggerPos <= tagEndPos &&
+ triggerPos > tagPos) ||
+ position.line < origTriggerLine
+ ) {
+ attributeNames = getAttributeNames(document, position, nsPrefix, tag)
+ return [true, isDfdlPrefix, attributeNames]
+ }
}
}
if (!isMultiLineTag || tagPos === -1) {
- return [false, isDfdlPrefix]
+ return [false, isDfdlPrefix, attributeNames]
}
//if this tag is part of a multi line set of annotations return true
//else this tag is not open return false
@@ -362,12 +384,13 @@ export function checkMultiLineTag(
tagLine: number,
tag: string,
isDfdlTag = false
-): [boolean, boolean] {
+): [boolean, boolean, string[]] {
if (nsPrefix === 'dfdl:') {
isDfdlTag = true
}
+ let attributeNames: string[] = []
if (itemsOnLine > 1) {
- return [false, isDfdlTag]
+ return [false, isDfdlTag, attributeNames]
}
let currentLine = position.line
let openTagLine = position.line
@@ -375,43 +398,42 @@ export function checkMultiLineTag(
const origText = document.lineAt(currentLine).text
let currentText = origText
- //the current line doesn't have the self close symbol
- if (!currentText.endsWith('/>')) {
- while (currentText.trim() === '' || !currentText.includes('<')) {
- --openTagLine
- currentText = document.lineAt(openTagLine).text
- if (currentText.includes('/>')) {
- closeTagLine = openTagLine
- }
- }
+ //Get the opening tag
+ while (
+ (currentText.trim() === '' ||
+ !currentText.includes('<' + nsPrefix + tag)) &&
+ openTagLine > 0
+ ) {
+ --openTagLine
+ currentText = document.lineAt(openTagLine).text
+ }
- if (
- currentText.indexOf('<' + nsPrefix + tag) !== -1 &&
- currentText.indexOf('>') === -1 &&
- currentText.indexOf('<' + nsPrefix + tag) &&
- openTagLine <= position.line &&
- closeTagLine >= position.line &&
- (origText.indexOf('>') > position.character ||
- origText.indexOf('>') === -1)
+ if (currentText.includes('<' + nsPrefix + tag)) {
+ let multiLineText = currentText.trim()
+ let closeText = document.lineAt(openTagLine).text
+
+ closeTagLine = openTagLine
+
+ //Get closing tag
+ while (
+ (closeText.trim() === '' || !closeText.includes('>')) &&
+ closeTagLine < document.lineCount
) {
- return [true, isDfdlTag]
+ ++closeTagLine
+ closeText = document.lineAt(closeTagLine).text
+ multiLineText += ' ' + closeText.trim()
}
- }
-
- if (currentText.endsWith('/>')) {
- let triggerPos = position.character
- let tagEndPos = currentText.indexOf('/>')
- let triggerLine = position.line
+ currentText = multiLineText
if (
- (triggerLine === currentLine && triggerPos < tagEndPos) ||
- (triggerLine === tagLine && triggerPos > tagPos && tagPos !== -1) ||
- triggerLine < currentLine
+ currentText.includes('<' + nsPrefix + tag) &&
+ currentText.includes('>')
) {
- return [true, isDfdlTag]
+ attributeNames = getAttributeNames(document, position, nsPrefix, tag)
+ return [true, isDfdlTag, attributeNames]
}
}
- return [false, isDfdlTag]
+ return [false, isDfdlTag, attributeNames]
}
//returns an empty value or a prefix plus a colon
@@ -437,6 +459,64 @@ export function getNsPrefix(
return defaultXsdNsPrefix
}
+export function getAttributeNames(
+ document: vscode.TextDocument,
+ position: vscode.Position,
+ nsPrefix: string,
+ tag: string
+): string[] {
+ let currentLine = position.line
+ let openTagLine = position.line
+ let closeTagLine = position.line
+ let currentText = document.lineAt(currentLine).text
+ let closeText = currentText
+
+ //if mulit-line tag
+ if (
+ !(
+ currentText.trim().startsWith('<' + nsPrefix + tag) &&
+ currentText.endsWith('>')
+ )
+ ) {
+ //Get the opening tag
+ while (
+ (currentText.trim() === '' ||
+ !currentText.includes('<' + nsPrefix + tag)) &&
+ openTagLine > -1
+ ) {
+ --openTagLine
+ currentText = document.lineAt(openTagLine).text
+ }
+
+ let multiLineText = currentText.trim()
+
+ closeTagLine = openTagLine
+
+ //Get closing tag
+ closeText = document.lineAt(openTagLine).text
+ while (
+ (closeText.trim() === '' || !closeText.includes('>')) &&
+ closeTagLine < document.lineCount
+ ) {
+ ++closeTagLine
+ closeText = document.lineAt(closeTagLine).text
+ multiLineText += ' ' + closeText.trim()
+ }
+ currentText = multiLineText
+ }
+
+ let attributeNames: string[] = []
+ const xmljs = xml2js(currentText, {})
+ const attributes = xmljs.elements?.[0].attributes
+ if (attributes) {
+ const attributeSet: Set<string> = new Set(Object.keys(attributes))
+ attributeNames = [...attributeSet]
+ return attributeNames
+ }
+
+ return attributeNames
+}
+
export function getItemsOnLineCount(triggerText: String) {
let itemsOnLine = 0
let nextPos = 0
diff --git a/src/tests/DfdlIntellisenseTestingChecklist.md
b/src/tests/DfdlIntellisenseTestingChecklist.md
index 17445f3..4b4ebdf 100644
--- a/src/tests/DfdlIntellisenseTestingChecklist.md
+++ b/src/tests/DfdlIntellisenseTestingChecklist.md
@@ -147,7 +147,7 @@ Select alignment from the dropdown. select 1 as the value
for alignment.
Place the cursor at line 33 column 1. Type CTRL+space.
-- [ ] Verify the dropdown contains dfdl:defineEscapeScheme, dfdl:defineFormat,
dfdl:defineVariable,and dfdl:format.
+- [ ] Verify the dropdown contains dfdl:defineEscapeScheme, dfdl:defineFormat,
,and dfdl:format.
Place the cursor at line 52 column 56 at the end of the line. Backspace over
the last two characters "/>". The cursor should be directly after
encoding="ascii". Type a / (slash '/').
diff --git a/src/tests/suite/language/items.test.ts
b/src/tests/suite/language/items.test.ts
index d4053bb..e959568 100644
--- a/src/tests/suite/language/items.test.ts
+++ b/src/tests/suite/language/items.test.ts
@@ -24,8 +24,10 @@ suite('Items Test Suite', () => {
const expectedElementItems = [
'xml version',
'schema',
+ 'element',
'element name',
'element ref',
+ 'group',
'group name',
'group ref',
'dfdl:assert',
@@ -34,13 +36,14 @@ suite('Items Test Suite', () => {
'annotation',
'appinfo',
'complexType',
- 'complexType name=',
+ 'complexType name',
'simpleType',
- 'simpleType name=',
+ 'simpleType name',
'sequence',
'choice',
'dfdl:newVariableInstance',
'dfdl:defineVariable',
+ 'dfdl:defineVariable name',
'dfdl:setVariable',
'dfdl:defineFormat',
'dfdl:defineEscapeScheme',