import { CUSTOM_TAGS } from "../model" ; import { ErrorCode , ExternalImportsCallbacks , Problem , YAMLDocument } from "./json" ; import noop = require ( "lodash/noop" ) ; import { Schema , Type } from "js-yaml" ; import { TextDocument } from "vscode-languageserver-types" ; import * as Yaml from "yaml-ast-parser-custom-tags" ; import { DocumentType } from "../model" ; import { getDocumentType } from "../utils" ; import { ParentParams } from "./json/document" ; export { YAMLDocument , Problem , ExternalImportsCallbacks } ; export * from "./json" ; export { collectReferencesFromStringNode } from "./references" ; function convertError ( e ) { return { message : `${ e . reason }` , location : { start : e . mark . position , end : e . mark . position + e . mark . column } , code : ErrorCode . Undefined } ; } function createJSONDocument ( document , yamlDoc , callbacks , parentParams ? ) { const doc = new YAMLDocument ( document . uri , parentParams ? DocumentType . UNKNOWN : getDocumentType ( document . getText ( ) ) , yamlDoc , callbacks , parentParams ) ; if ( ! yamlDoc || ! doc . root ) { doc . errors . push ( { message : "Expected a YAML object, array or literal" , code : ErrorCode . Undefined , location : yamlDoc ? { start : yamlDoc . startPosition , end : yamlDoc . endPosition } : { start : 0 , end : 0 } } ) ; return doc ; } const duplicateKeyReason = "duplicate key" ; const isDuplicateAndNotMergeKey = ( error , yamlText ) => { const errorConverted = convertError ( error ) ; const errorStart = errorConverted . location . start ; const errorEnd = errorConverted . location . end ; if ( error . reason === duplicateKeyReason && yamlText . substring ( errorStart , errorEnd ) . startsWith ( "<<" ) ) { return false ; } return true ; } ; doc . errors = yamlDoc . errors . filter ( e => e . reason !== duplicateKeyReason && ! e . isWarning ) . map ( e => convertError ( e ) ) ; doc . warnings = yamlDoc . errors . filter ( e => ( e . reason === duplicateKeyReason && isDuplicateAndNotMergeKey ( e , document . getText ( ) ) ) || e . isWarning ) . map ( e => convertError ( e ) ) ; return doc ; } export const parse = ( document , callbacks = { onRegisterExternalImport : noop , onValidateExternalImport : noop } , parentParams ? ) : YAMLDocument => { const compiledTypeMap = { } ; CUSTOM_TAGS . forEach ( customTag => { if ( customTag . tag ) { const [ kind , ... additionalKinds ] = customTag . kind ; compiledTypeMap [ customTag . tag ] = new Type ( customTag . tag , { kind , construct : data => { if ( data ) { data . customTag = customTag ; return data ; } return null ; } } ) ; compiledTypeMap [ customTag . tag ] . additionalKinds = additionalKinds ; } } ) ; const schemaWithAdditionalTags = Schema . create ( Object . values ( compiledTypeMap ) ) ; ( schemaWithAdditionalTags as any ) . compiledTypeMap = compiledTypeMap ; const additionalOptions = { schema : schemaWithAdditionalTags } ; const text = document . getText ( ) ; return createJSONDocument ( document , Yaml . load ( text , additionalOptions ) , callbacks , parentParams ) ; } ;