in src/yaml/aslYamlLanguageService.ts [75:281]
export const getLanguageService = function (
params: LanguageServiceParams,
schema: JSONSchema,
aslLanguageService: LanguageService,
): LanguageService {
const builtInParams = {}
const languageService = getLanguageServiceVscode({
...params,
...builtInParams,
})
const requestServiceMock = async function (_uri: string): Promise<string> {
return new Promise<string>((c) => {
c(JSON.stringify(schema))
})
}
const schemaService = new YAMLSchemaService(requestServiceMock, params.workspaceContext)
// initialize schema
schemaService.registerExternalSchema(LANGUAGE_IDS.YAML, ['*'], schema)
schemaService.getOrAddSchemaHandle(LANGUAGE_IDS.YAML, schema)
const completer = new YAMLCompletion(schemaService)
const formatter = new YAMLFormatter()
languageService.doValidation = async function (textDocument: TextDocument) {
const yamlDocument: YAMLDocument = parseYAML(textDocument.getText())
const validationResult: Diagnostic[] = []
for (const currentYAMLDoc of yamlDocument.documents) {
const validation = await aslLanguageService.doValidation(textDocument, currentYAMLDoc)
validationResult.push(
...currentYAMLDoc.errors.concat(currentYAMLDoc.warnings).map((err) => convertYAMLDiagnostic(err, textDocument)),
)
validationResult.push(...validation)
}
return validationResult
}
languageService.doComplete = async function (document: TextDocument, position: Position): Promise<CompletionList> {
const {
modifiedDocText,
tempPositionForCompletions,
startPositionForInsertion,
endPositionForInsertion,
shouldPrependSpace,
} = processYamlDocForCompletion(document, position)
const processedDocument = TextDocument.create(document.uri, document.languageId, document.version, modifiedDocText)
const offsetIntoOriginalDocument = document.offsetAt(position)
const offsetIntoProcessedDocument = processedDocument.offsetAt(tempPositionForCompletions)
const processedYamlDoc: YAMLDocument = parseYAML(modifiedDocText)
const currentDoc = matchOffsetToDocument(offsetIntoProcessedDocument, processedYamlDoc)
if (!currentDoc) {
return { items: [], isIncomplete: false }
}
const positionForDoComplete = { ...tempPositionForCompletions } // Copy position to new object since doComplete modifies the position
const yamlCompletions = await completer.doComplete(processedDocument, positionForDoComplete, false)
// yaml-language-server does not output correct completions for retry/catch
// we need to overwrite the text
function updateCompletionText(item: CompletionItem, text: string) {
item.insertText = text
if (item.textEdit) {
item.textEdit.newText = text
}
}
yamlCompletions.items.forEach((item) => {
if (item.label === 'Catch') {
updateCompletionText(item, CATCH_INSERT)
} else if (item.label === 'Retry') {
updateCompletionText(item, RETRY_INSERT)
}
})
const { isDirectChildOfStates, isWithinCatchRetryState, hasCatchPropSibling, hasRetryPropSibling } = getOffsetData(
document,
offsetIntoOriginalDocument,
)
const aslOptions: ASLOptions = {
ignoreColonOffset: true,
shouldShowStateSnippets: isDirectChildOfStates,
shouldShowErrorSnippets: {
retry: isWithinCatchRetryState && !hasRetryPropSibling,
catch: isWithinCatchRetryState && !hasCatchPropSibling,
},
}
const aslCompletions: CompletionList = await doCompleteAsl(
processedDocument,
tempPositionForCompletions,
currentDoc,
yamlCompletions,
aslOptions,
)
const modifiedAslCompletionItems: CompletionItem[] = aslCompletions.items.map((completionItem) => {
const completionItemCopy = { ...completionItem } // Copy completion to new object to avoid overwriting any snippets
if (
completionItemCopy.insertText &&
completionItemCopy.kind === CompletionItemKind.Snippet &&
document.languageId === LANGUAGE_IDS.YAML
) {
completionItemCopy.insertText = convertJsonSnippetToYaml(completionItemCopy.insertText)
} else {
const currentTextEdit = completionItemCopy.textEdit
if (currentTextEdit) {
if (shouldPrependSpace) {
if (currentTextEdit.newText && currentTextEdit.newText.charAt(0) !== ' ') {
currentTextEdit.newText = ' ' + currentTextEdit.newText
}
if (completionItemCopy.insertText && completionItemCopy.insertText.charAt(0) !== ' ') {
completionItemCopy.insertText = ' ' + completionItemCopy.insertText
}
}
if (TextEdit.is(currentTextEdit)) {
currentTextEdit.range.start = startPositionForInsertion
currentTextEdit.range.end = endPositionForInsertion
// Completions that include both a key and a value should replace everything right of the cursor.
if (completionItemCopy.kind === CompletionItemKind.Property) {
currentTextEdit.range.end = {
line: endPositionForInsertion.line,
character: document.getText().length,
}
}
}
}
}
return completionItemCopy
})
const modifiedAslCompletions: CompletionList = {
isIncomplete: aslCompletions.isIncomplete,
items: modifiedAslCompletionItems,
}
return Promise.resolve(modifiedAslCompletions)
}
languageService.doHover = function (document: TextDocument, position: Position): Thenable<Hover | null> {
const doc = parseYAML(document.getText())
const offset = document.offsetAt(position)
const currentDoc = matchOffsetToDocument(offset, doc)
if (!currentDoc) {
// tslint:disable-next-line: no-null-keyword
return Promise.resolve(null)
}
const currentDocIndex = doc.documents.indexOf(currentDoc)
currentDoc.currentDocIndex = currentDocIndex
return aslLanguageService.doHover(document, position, currentDoc)
}
languageService.format = function (document: TextDocument, range: Range, options: FormattingOptions): TextEdit[] {
try {
return formatter.format(document, options)
} catch (error) {
return []
}
}
languageService.findDocumentSymbols = function (document: TextDocument): SymbolInformation[] {
const doc = parseYAML(document.getText())
if (!doc || doc.documents.length === 0) {
return []
}
let results: any[] = []
for (const yamlDoc of doc.documents) {
if (yamlDoc.root) {
results = results.concat(aslLanguageService.findDocumentSymbols(document, yamlDoc))
}
}
return results
}
languageService.findDocumentSymbols2 = function (document: TextDocument): DocumentSymbol[] {
const doc = parseYAML(document.getText())
if (!doc || doc.documents.length === 0) {
return []
}
let results: any[] = []
for (const yamlDoc of doc.documents) {
if (yamlDoc.root) {
results = results.concat(aslLanguageService.findDocumentSymbols2(document, yamlDoc))
}
}
return results
}
return languageService
}