blob: bbf60eaf2f9bd3824e0c13dffa606ad7cdde7674 [file] [log] [blame]
/*
* 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 {
nearestOpen,
checkBraceOpen,
lineCount,
checkLastItemOpen,
checkSequenceOpen,
checkElementOpen,
checkSimpleTypeOpen,
} from './utils'
import { attributeCompletion } from './intellisense/attributeItems'
import { getCommonItems, createCompletionItem } from './utils'
function getCompletionItems(
itemsToUse: string[],
preVal: string = '',
additionalItems: string = ''
) {
let compItems: vscode.CompletionItem[] = getCommonItems(
itemsToUse,
preVal,
additionalItems
)
attributeCompletion(additionalItems).items.forEach((e) => {
if (itemsToUse.includes(e.item)) {
const completionItem = createCompletionItem(e, preVal)
compItems.push(completionItem)
}
})
return compItems
}
export function getAttributeCompletionProvider() {
return vscode.languages.registerCompletionItemProvider(
{ language: 'dfdl' },
{
provideCompletionItems(
document: vscode.TextDocument,
position: vscode.Position
) {
const wholeLine = document
.lineAt(position)
.text.substr(0, position.character)
var nearestOpenItem = nearestOpen(document, position)
if (
!checkBraceOpen(document, position) &&
!wholeLine.includes('assert') &&
!nearestOpenItem.includes('none')
) {
if (nearestOpenItem.includes('element')) {
var preVal = ''
if (!wholeLine.includes('xs:element')) {
if (lineCount(document, position) === 1) {
preVal = '\t'
} else {
preVal = ''
}
}
var additionalItems = getDefinedTypes(document)
if (
checkLastItemOpen(document, position) &&
(wholeLine.includes('<xs:element name="') ||
wholeLine.includes('<xs:element ref="') ||
checkElementOpen(document, position))
) {
return getCompletionItems(
[
'dfdl:defineFormat',
'dfdl:defineEscapeScheme',
'type=',
'minOccurs=',
'maxOccurs=',
'dfdl:occursCount=',
'dfdl:byteOrder=',
'dfdl:occursCountKind=',
'dfdl:length=',
'dfdl:lengthKind=',
'dfdl:encoding=',
'dfdl:alignment=',
'dfdl:lengthUnits=',
'dfdl:lengthPattern=',
'dfdl:inputValueCalc=',
'dfdl:outputValueCalc=',
'dfdl:alignmentUnits=',
'dfdl:terminator=',
'dfdl:outputNewLine=',
'dfdl:choiceBranchKey=',
'dfdl:representation',
],
preVal,
additionalItems
)
}
}
if (nearestOpenItem.includes('sequence')) {
var preVal = ''
if (!wholeLine.includes('xs:sequence')) {
if (lineCount(document, position) === 1) {
preVal = '\t'
} else {
preVal = ''
}
}
if (
checkLastItemOpen(document, position) &&
(wholeLine.includes('<xs:sequence') ||
checkSequenceOpen(document, position))
) {
return getCompletionItems(
[
'dfdl:hiddenGroupRef=',
'dfdl:sequenceKind=',
'dfdl:separator=',
'dfdl:separatorPosition=',
'dfdl:separatorSuppressionPolicy',
],
preVal
)
}
}
if (wholeLine.includes('choice')) {
if (!wholeLine.includes('>')) {
return getCompletionItems([
'dfdl:choiceLengthKind=',
'dfdl:choiceLength=',
'dfdl:intiatedContent=',
'dfdl:choiceDispatchKey=',
'dfdl:choiceBranchKey=',
])
}
}
if (
wholeLine.includes('simpleType') ||
checkSimpleTypeOpen(document, position)
) {
if (!wholeLine.includes('>')) {
return getCompletionItems([
'dfdl:length=',
'dfdl:lengthKind=',
'dfdl:simpleType',
'dfdl:simpleType',
'xs:restriction',
])
}
}
if (wholeLine.includes('defineVariable')) {
var preVal = ''
if (!wholeLine.includes('dfdl:defineVariable')) {
if (lineCount(document, position) === 1) {
preVal = '\t'
} else {
preVal = ''
}
}
var additionalItems = getDefinedTypes(document)
var xmlItems = [
{
item: 'external=',
snippetString: preVal + 'external="${1|true,false|}"$0',
},
{
item: 'defaultValue=',
snippetString: preVal + 'defaultValue="0$1"$0',
},
]
if (!wholeLine.includes('>')) {
let compItems: vscode.CompletionItem[] = []
xmlItems.forEach((e) => {
const completionItem = new vscode.CompletionItem(e.item)
completionItem.insertText = new vscode.SnippetString(
e.snippetString
)
compItems.push(completionItem)
})
getCommonItems(['type='], '', additionalItems).forEach((ci) => {
compItems.push(ci)
})
return compItems
}
}
if (nearestOpenItem.includes('setVariable')) {
var preVal = ''
if (!wholeLine.includes('dfdl:setVariable')) {
if (lineCount(document, position) === 1) {
preVal = '\t'
} else {
preVal = ''
}
}
const xmlValue = new vscode.CompletionItem('value=')
xmlValue.insertText = new vscode.SnippetString('value="$1"$0')
xmlValue.documentation = new vscode.MarkdownString('')
if (!wholeLine.includes('>')) {
return [xmlValue]
}
}
}
return undefined
},
},
' ',
'\n' // triggered whenever a newline is typed
)
}
function getDefinedTypes(document: vscode.TextDocument) {
var additionalTypes = ''
var lineNum = 0
const lineCount = document.lineCount
while (lineNum !== lineCount) {
const wholeLine = document
.lineAt(lineNum)
.text.substring(0, document.lineAt(lineNum).range.end.character)
if (
wholeLine.includes('xs:simpleType Name=') ||
wholeLine.includes('xs:complexType Name=')
) {
var startPos = wholeLine.indexOf('"', 0)
var endPos = wholeLine.indexOf('"', startPos + 1)
var newType = wholeLine.substring(startPos + 1, endPos)
additionalTypes = String(additionalTypes + ',' + newType)
}
++lineNum
}
return additionalTypes
}