'use strict' ; import * as path from 'path' ; import { workspace , languages , ExtensionContext , extensions , Uri } from 'vscode' ; import { LanguageClient , LanguageClientOptions , RequestType , ServerOptions , TransportKind , NotificationType } from 'vscode-languageclient' ; import TelemetryReporter from 'vscode-extension-telemetry' ; import * as nls from 'vscode-nls' ; let localize = nls . loadMessageBundle ( ) ; namespace VSCodeContentRequest { export const type = { get method ( ) { return 'vscode/content' ; } } ; } export interface ISchemaAssociations { [ pattern ] : string [ ] ; } namespace SchemaAssociationNotification { export const type = { get method ( ) { return 'json/schemaAssociations' ; } } ; } interface IPackageInfo { name : string ; version : string ; aiKey : string ; } export function activate ( context ) { let packageInfo = getPackageInfo ( context ) ; let telemetryReporter = packageInfo && new TelemetryReporter ( packageInfo . name , packageInfo . version , packageInfo . aiKey ) ; languages . getLanguages ( ) . then ( languageIds => { let serverModule = context . asAbsolutePath ( path . join ( 'server' , 'out' , 'jsonServerMain.js' ) ) ; let debugOptions = { execArgv : [ '--nolazy' , '--debug=6004' ] } ; let serverOptions = { run : { module : serverModule , transport : TransportKind . ipc } , debug : { module : serverModule , transport : TransportKind . ipc , options : debugOptions } } ; let clientOptions = { documentSelector : [ 'json' ] , synchronize : { configurationSection : [ 'json.schemas' , 'http.proxy' , 'http.proxyStrictSSL' ] , fileEvents : workspace . createFileSystemWatcher ( '**/*.json' ) } , initializationOptions : { languageIds } } ; let client = new LanguageClient ( 'json' , localize ( 'jsonserver.name' , 'JSON Language Server' ) , serverOptions , clientOptions ) ; client . onTelemetry ( e => { if ( telemetryReporter ) { telemetryReporter . sendTelemetryEvent ( e . key , e . data ) ; } } ) ; client . onRequest ( VSCodeContentRequest . type , ( uriPath ) => { let uri = Uri . parse ( uriPath ) ; return workspace . openTextDocument ( uri ) . then ( doc => { return doc . getText ( ) ; } , error => { return Promise . reject ( error ) ; } ) ; } ) ; let disposable = client . start ( ) ; client . sendNotification ( SchemaAssociationNotification . type , getSchemaAssociation ( context ) ) ; context . subscriptions . push ( disposable ) ; languages . setLanguageConfiguration ( 'json' , { wordPattern : /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/ } ) ; } ) ; } function getSchemaAssociation ( context ) { let associations = { } ; extensions . all . forEach ( extension => { let packageJSON = extension . packageJSON ; if ( packageJSON && packageJSON . contributes && packageJSON . contributes . jsonValidation ) { let jsonValidation = packageJSON . contributes . jsonValidation ; if ( Array . isArray ( jsonValidation ) ) { jsonValidation . forEach ( jv => { let { fileMatch , url } = jv ; if ( fileMatch && url ) { if ( url [ 0 ] === '.' && url [ 1 ] === '/' ) { url = Uri . file ( path . join ( extension . extensionPath , url ) ) . toString ( ) ; } if ( fileMatch [ 0 ] === '%' ) { fileMatch = fileMatch . replace ( /%APP_SETTINGS_HOME%/ , '/User' ) ; } else if ( fileMatch . charAt ( 0 ) !== '/' && ! fileMatch . match ( /\w+:\/\// ) ) { fileMatch = '/' + fileMatch ; } let association = associations [ fileMatch ] ; if ( ! association ) { association = [ ] ; associations [ fileMatch ] = association ; } association . push ( url ) ; } } ) ; } } } ) ; return associations ; } function getPackageInfo ( context ) { let extensionPackage = require ( context . asAbsolutePath ( './package.json' ) ) ; if ( extensionPackage ) { return { name : extensionPackage . name , version : extensionPackage . version , aiKey : extensionPackage . aiKey } ; } return null ; }