import { URI } from 'vscode-uri' ; import { CommonLanguageClient as LanguageClient , RequestType } from 'vscode-languageclient/node' ; import { workspace } from 'vscode' ; import { logToExtensionOutputChannel } from './extension' ; interface SchemaContributorProvider { readonly requestSchema : ( resource : string ) => string ; readonly requestSchemaContent : ( uri : string ) => Promise < string > | string ; readonly label ? : string ; } export enum MODIFICATION_ACTIONS { 'delete' , 'add' } export interface SchemaAdditions { schema : string ; action : MODIFICATION_ACTIONS . add ; path : string ; key : string ; content : unknown ; } export interface SchemaDeletions { schema : string ; action : MODIFICATION_ACTIONS . delete ; path : string ; key : string ; } namespace SchemaModificationNotification { export const type = new RequestType ( 'json/schema/modify' ) ; } export interface ExtensionAPI { registerContributor ( schema , requestSchema , requestSchemaContent , label ? ) : boolean ; modifySchemaContent ( schemaModifications ) : Promise < void > ; } class SchemaExtensionAPI implements ExtensionAPI { private _customSchemaContributors : { [ index ] : SchemaContributorProvider ; } = { } ; private _yamlClient : LanguageClient ; constructor ( client ) { this . _yamlClient = client ; } param { string } the param requestSchema param requestSchemaContent param label returns { boolean } public registerContributor ( schema , requestSchema , requestSchemaContent , label ? ) { if ( this . _customSchemaContributors [ schema ] ) { return false ; } if ( ! requestSchema ) { throw new Error ( 'Illegal parameter for requestSchema.' ) ; } if ( label ) { const [ first , second ] = label . split ( ':' ) ; if ( first && second ) { label = second . trim ( ) ; label = label . replace ( '.' , '\\.' ) ; label = `${ first }:[\t ]+${ label }` ; } } this . _customSchemaContributors [ schema ] = < SchemaContributorProvider > { requestSchema , requestSchemaContent , label , } ; return true ; } param { string } resource returns { string } public requestCustomSchema ( resource ) { const matches = [ ] ; for ( const customKey of Object . keys ( this . _customSchemaContributors ) ) { try { const contributor = this . _customSchemaContributors [ customKey ] ; let uri ; if ( contributor . label && workspace . textDocuments ) { const labelRegexp = new RegExp ( contributor . label , 'g' ) ; for ( const doc of workspace . textDocuments ) { if ( doc . uri . toString ( ) === resource ) { if ( labelRegexp . test ( doc . getText ( ) ) ) { uri = contributor . requestSchema ( resource ) ; return [ uri ] ; } } } } uri = contributor . requestSchema ( resource ) ; if ( uri ) { matches . push ( uri ) ; } } catch ( error ) { logToExtensionOutputChannel ( `Error thrown while requesting schema "${ error }" when calling the registered contributor "${ customKey }"` ) ; } } return matches ; } param { string } uri returns { string } public requestCustomSchemaContent ( uri ) { if ( uri ) { const _uri = URI . parse ( uri ) ; if ( _uri . scheme && this . _customSchemaContributors [ _uri . scheme ] && this . _customSchemaContributors [ _uri . scheme ] . requestSchemaContent ) { return this . _customSchemaContributors [ _uri . scheme ] . requestSchemaContent ( uri ) ; } } } public async modifySchemaContent ( schemaModifications ) { return this . _yamlClient . sendRequest ( SchemaModificationNotification . type , schemaModifications ) ; } public hasProvider ( schema ) { return this . _customSchemaContributors [ schema ] !== undefined ; } } export const CUSTOM_SCHEMA_REQUEST = 'custom/schema/request' ; export const CUSTOM_CONTENT_REQUEST = 'custom/schema/content' ; export { SchemaExtensionAPI } ;