jsonMain.ts 5.0 KB
Newer Older
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import * as path from 'path';

J
Johannes Rieken 已提交
9 10
import { workspace, languages, ExtensionContext, extensions, Uri } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType } from 'vscode-languageclient';
11
import TelemetryReporter from 'vscode-extension-telemetry';
12

13 14 15
import * as nls from 'vscode-nls';
let localize = nls.loadMessageBundle();

16
namespace VSCodeContentRequest {
17
	export const type: RequestType<string, string, any, any> = { get method() { return 'vscode/content'; }, _: null };
18 19 20 21 22 23 24
}

export interface ISchemaAssociations {
	[pattern: string]: string[];
}

namespace SchemaAssociationNotification {
25
	export const type: NotificationType<ISchemaAssociations, any> = { get method() { return 'json/schemaAssociations'; }, _: null };
26 27
}

28 29 30 31 32 33
interface IPackageInfo {
	name: string;
	version: string;
	aiKey: string;
}

34
export function activate(context: ExtensionContext) {
35

36 37
	let packageInfo = getPackageInfo(context);
	let telemetryReporter: TelemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
38

B
Benjamin Pasero 已提交
39 40 41 42
	// Resolve language ids to pass around as initialization data
	languages.getLanguages().then(languageIds => {

		// The server is implemented in node
43
		let serverModule = context.asAbsolutePath(path.join('server', 'out', 'jsonServerMain.js'));
B
Benjamin Pasero 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
		// The debug options for the server
		let debugOptions = { execArgv: ['--nolazy', '--debug=6004'] };

		// If the extension is launch in debug mode the debug server options are use
		// Otherwise the run options are used
		let serverOptions: ServerOptions = {
			run: { module: serverModule, transport: TransportKind.ipc },
			debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
		};

		// Options to control the language client
		let clientOptions: LanguageClientOptions = {
			// Register the server for json documents
			documentSelector: ['json'],
			synchronize: {
				// Synchronize the setting section 'json' to the server
				configurationSection: ['json.schemas', 'http.proxy', 'http.proxyStrictSSL'],
61
				fileEvents: workspace.createFileSystemWatcher('**/*.json')
B
Benjamin Pasero 已提交
62 63
			},
			initializationOptions: {
J
Johannes Rieken 已提交
64 65
				languageIds,
				['format.enable']: workspace.getConfiguration('json').get('format.enable')
B
Benjamin Pasero 已提交
66 67 68 69
			}
		};

		// Create the language client and start the client.
70
		let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
71 72 73 74 75 76
		let disposable = client.start();
		client.onReady().then(() => {
			client.onTelemetry(e => {
				if (telemetryReporter) {
					telemetryReporter.sendTelemetryEvent(e.key, e.data);
				}
B
Benjamin Pasero 已提交
77
			});
78

79 80 81 82 83 84 85 86 87
			// handle content request
			client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
				let uri = Uri.parse(uriPath);
				return workspace.openTextDocument(uri).then(doc => {
					return doc.getText();
				}, error => {
					return Promise.reject(error);
				});
			});
B
Benjamin Pasero 已提交
88

89 90
			client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
		});
B
Benjamin Pasero 已提交
91 92 93 94 95 96

		// Push the disposable to the context's subscriptions so that the
		// client can be deactivated on extension deactivation
		context.subscriptions.push(disposable);

		languages.setLanguageConfiguration('json', {
97
			wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/
B
Benjamin Pasero 已提交
98
		});
99
	});
100 101
}

J
Johannes Rieken 已提交
102 103
function getSchemaAssociation(context: ExtensionContext): ISchemaAssociations {
	let associations: ISchemaAssociations = {};
104
	extensions.all.forEach(extension => {
105
		let packageJSON = extension.packageJSON;
106
		if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation) {
107
			let jsonValidation = packageJSON.contributes.jsonValidation;
108 109
			if (Array.isArray(jsonValidation)) {
				jsonValidation.forEach(jv => {
110
					let {fileMatch, url} = jv;
111
					if (fileMatch && url) {
112
						if (url[0] === '.' && url[1] === '/') {
113
							url = Uri.file(path.join(extension.extensionPath, url)).toString();
114
						}
115 116 117 118 119
						if (fileMatch[0] === '%') {
							fileMatch = fileMatch.replace(/%APP_SETTINGS_HOME%/, '/User');
						} else if (fileMatch.charAt(0) !== '/' && !fileMatch.match(/\w+:\/\//)) {
							fileMatch = '/' + fileMatch;
						}
120
						let association = associations[fileMatch];
121 122 123 124 125 126 127 128 129
						if (!association) {
							association = [];
							associations[fileMatch] = association;
						}
						association.push(url);
					}
				});
			}
		}
130
	});
131
	return associations;
132 133
}

134 135
function getPackageInfo(context: ExtensionContext): IPackageInfo {
	let extensionPackage = require(context.asAbsolutePath('./package.json'));
136 137 138 139 140 141 142
	if (extensionPackage) {
		return {
			name: extensionPackage.name,
			version: extensionPackage.version,
			aiKey: extensionPackage.aiKey
		};
	}
143
	return null;
144
}