export const getLanguageService = function()

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
}