Merge from vscode 4d91d96e5e121b38d33508cdef17868bab255eae

This commit is contained in:
ADS Merger
2020-06-18 04:32:54 +00:00
committed by AzureDataStudio
parent a971aee5bd
commit 5e7071e466
1002 changed files with 24201 additions and 13193 deletions

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext } from 'vscode';
import { LanguageClientOptions } from 'vscode-languageclient';
import { startClient, LanguageClientConstructor } from '../jsonClient';
import { LanguageClient } from 'vscode-languageclient/browser';
import { RequestService } from '../requests';
declare const Worker: {
new(stringUrl: string): any;
};
declare function fetch(uri: string, options: any): any;
// this method is called when vs code is activated
export function activate(context: ExtensionContext) {
const serverMain = context.asAbsolutePath('server/dist/browser/jsonServerMain.js');
try {
const worker = new Worker(serverMain);
const newLanguageClient: LanguageClientConstructor = (id: string, name: string, clientOptions: LanguageClientOptions) => {
return new LanguageClient(id, name, clientOptions, worker);
};
const http: RequestService = {
getContent(uri: string) {
return fetch(uri, { mode: 'cors' })
.then(function (response: any) {
return response.text();
});
}
};
startClient(context, newLanguageClient, { http });
} catch (e) {
console.log(e);
}
}

View File

@@ -2,11 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import * as fs from 'fs';
import * as nls from 'vscode-nls';
import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
const localize = nls.loadMessageBundle();
@@ -16,13 +12,13 @@ import {
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext, Hover, MarkdownString,
} from 'vscode';
import {
LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType,
LanguageClientOptions, RequestType, NotificationType,
DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams,
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, ProvideHoverSignature
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, ProvideHoverSignature, CommonLanguageClient
} from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
import { hash } from './utils/hash';
import { RequestService, joinPath } from './requests';
namespace VSCodeContentRequest {
export const type: RequestType<string, string, any, any> = new RequestType('vscode/content');
@@ -53,12 +49,6 @@ namespace ResultLimitReachedNotification {
export const type: NotificationType<string, any> = new NotificationType('json/resultLimitReached');
}
interface IPackageInfo {
name: string;
version: string;
aiKey: string;
}
interface Settings {
json?: {
schemas?: JSONSchemaSettings[];
@@ -83,29 +73,27 @@ namespace SettingIds {
export const maxItemsComputed = 'json.maxItemsComputed';
}
let telemetryReporter: TelemetryReporter | undefined;
export interface TelemetryReporter {
sendTelemetryEvent(eventName: string, properties?: {
[key: string]: string;
}, measurements?: {
[key: string]: number;
}): void;
}
export function activate(context: ExtensionContext) {
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => CommonLanguageClient;
export interface Runtime {
http: RequestService;
telemetry?: TelemetryReporter
}
export function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime) {
const toDispose = context.subscriptions;
let rangeFormatting: Disposable | undefined = undefined;
const packageInfo = getPackageInfo(context);
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
const serverMain = readJSONFile(context.asAbsolutePath('./server/package.json')).main;
const serverModule = context.asAbsolutePath(path.join('server', serverMain));
// The debug options for the server
const debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
// If the extension is launch in debug mode the debug server options are use
// Otherwise the run options are used
const serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
};
const documentSelector = ['json', 'jsonc'];
@@ -119,6 +107,7 @@ export function activate(context: ExtensionContext) {
toDispose.push(schemaResolutionErrorStatusBarItem);
const fileSchemaErrors = new Map<string, string>();
let schemaDownloadEnabled = true;
// Options to control the language client
const clientOptions: LanguageClientOptions = {
@@ -139,7 +128,7 @@ export function activate(context: ExtensionContext) {
didChangeConfiguration: () => client.sendNotification(DidChangeConfigurationNotification.type, { settings: getSettings() })
},
handleDiagnostics: (uri: Uri, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature) => {
const schemaErrorIndex = diagnostics.findIndex(candidate => candidate.code === /* SchemaResolveError */ 0x300);
const schemaErrorIndex = diagnostics.findIndex(isSchemaResolveError);
if (schemaErrorIndex === -1) {
fileSchemaErrors.delete(uri.toString());
@@ -149,6 +138,10 @@ export function activate(context: ExtensionContext) {
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
fileSchemaErrors.set(uri.toString(), schemaResolveDiagnostic.message);
if (!schemaDownloadEnabled) {
diagnostics = diagnostics.filter(d => !isSchemaResolveError(d));
}
if (window.activeTextEditor && window.activeTextEditor.document.uri.toString() === uri.toString()) {
schemaResolutionErrorStatusBarItem.show();
}
@@ -197,49 +190,39 @@ export function activate(context: ExtensionContext) {
};
// Create the language client and start the client.
const client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
const client = newLanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), clientOptions);
client.registerProposedFeatures();
const disposable = client.start();
toDispose.push(disposable);
client.onReady().then(() => {
const schemaDocuments: { [uri: string]: boolean } = {};
let schemaDownloadEnabled = true;
// handle content request
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
const uri = Uri.parse(uriPath);
if (uri.scheme === 'untitled') {
return Promise.reject(new Error(localize('untitled.schema', 'Unable to load {0}', uri.toString())));
return Promise.reject(new ResponseError(3, localize('untitled.schema', 'Unable to load {0}', uri.toString())));
}
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
return workspace.openTextDocument(uri).then(doc => {
schemaDocuments[uri.toString()] = true;
return doc.getText();
}, error => {
return Promise.reject(error);
return Promise.reject(new ResponseError(2, error.toString()));
});
} else if (schemaDownloadEnabled) {
if (telemetryReporter && uri.authority === 'schema.management.azure.com') {
if (runtime.telemetry && uri.authority === 'schema.management.azure.com') {
/* __GDPR__
"json.schema" : {
"schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
telemetryReporter.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
runtime.telemetry.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
}
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uriPath, followRedirects: 5, headers }).then(response => {
return response.responseText;
}, (error: XHRResponse) => {
let extraInfo = error.responseText || error.toString();
if (extraInfo.length > 256) {
extraInfo = `${extraInfo.substr(0, 256)}...`;
}
return Promise.reject(new ResponseError(error.status, getErrorStatusDescription(error.status) + '\n' + extraInfo));
});
return runtime.http.getContent(uriPath);
} else {
return Promise.reject(localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload));
return Promise.reject(new ResponseError(1, localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload)));
}
});
@@ -280,7 +263,7 @@ export function activate(context: ExtensionContext) {
schemaResolutionErrorStatusBarItem.text = '$(watch)';
const activeDocUri = window.activeTextEditor.document.uri.toString();
client.sendRequest(ForceValidateRequest.type, activeDocUri).then((diagnostics) => {
const schemaErrorIndex = diagnostics.findIndex(candidate => candidate.code === /* SchemaResolveError */ 0x300);
const schemaErrorIndex = diagnostics.findIndex(isSchemaResolveError);
if (schemaErrorIndex !== -1) {
// Show schema resolution errors in status bar only; ref: #51032
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
@@ -335,7 +318,7 @@ export function activate(context: ExtensionContext) {
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
client.protocol2CodeConverter.asTextEdits,
(error) => {
client.logFailedRequest(DocumentRangeFormattingRequest.type, error);
client.handleFailedRequest(DocumentRangeFormattingRequest.type, error, []);
return Promise.resolve([]);
}
);
@@ -370,12 +353,6 @@ export function activate(context: ExtensionContext) {
}
export function deactivate(): Promise<any> {
return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null);
}
function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[] {
const associations: ISchemaAssociation[] = [];
extensions.all.forEach(extension => {
@@ -388,9 +365,10 @@ function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[]
if (typeof fileMatch === 'string') {
fileMatch = [fileMatch];
}
if (Array.isArray(fileMatch) && url) {
if (url[0] === '.' && url[1] === '/') {
url = Uri.file(path.join(extension.extensionPath, url)).toString();
if (Array.isArray(fileMatch) && typeof url === 'string') {
let uri: string = url;
if (uri[0] === '.' && uri[1] === '/') {
uri = joinPath(extension.extensionUri, uri).toString();
}
fileMatch = fileMatch.map(fm => {
if (fm[0] === '%') {
@@ -402,7 +380,7 @@ function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[]
}
return fm;
});
associations.push({ fileMatch, uri: url });
associations.push({ fileMatch, uri });
}
});
}
@@ -504,39 +482,18 @@ function getSettings(): Settings {
return settings;
}
function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri) {
function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri): string | undefined {
let url = schema.url;
if (!url) {
if (schema.schema) {
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
}
} else if (folderUri && (url[0] === '.' || url[0] === '/')) {
url = folderUri.with({ path: path.posix.join(folderUri.path, url) }).toString();
url = joinPath(folderUri, url).toString();
}
return url;
}
function getPackageInfo(context: ExtensionContext): IPackageInfo | undefined {
const extensionPackage = readJSONFile(context.asAbsolutePath('./package.json'));
if (extensionPackage) {
return {
name: extensionPackage.name,
version: extensionPackage.version,
aiKey: extensionPackage.aiKey
};
}
return undefined;
}
function readJSONFile(location: string) {
try {
return JSON.parse(fs.readFileSync(location).toString());
} catch (e) {
console.log(`Problems reading ${location}: ${e}`);
return {};
}
}
function isThenable<T>(obj: ProviderResult<T>): obj is Thenable<T> {
return obj && (<any>obj)['then'];
}
@@ -546,3 +503,7 @@ function updateMarkdownString(h: MarkdownString): MarkdownString {
n.isTrusted = h.isTrusted;
return n;
}
function isSchemaResolveError(d: Diagnostic) {
return d.code === /* SchemaResolveError */ 0x300;
}

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext } from 'vscode';
import { startClient, LanguageClientConstructor } from '../jsonClient';
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient } from 'vscode-languageclient/node';
import * as fs from 'fs';
import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
import TelemetryReporter from 'vscode-extension-telemetry';
import { RequestService } from '../requests';
let telemetry: TelemetryReporter | undefined;
// this method is called when vs code is activated
export function activate(context: ExtensionContext) {
const clientPackageJSON = getPackageInfo(context);
telemetry = new TelemetryReporter(clientPackageJSON.name, clientPackageJSON.version, clientPackageJSON.aiKey);
const serverMain = `./server/${clientPackageJSON.main.indexOf('/dist/') !== -1 ? 'dist' : 'out'}/node/jsonServerMain`;
const serverModule = context.asAbsolutePath(serverMain);
// The debug options for the server
const debugOptions = { execArgv: ['--nolazy', '--inspect=6044'] };
// If the extension is launch in debug mode the debug server options are use
// Otherwise the run options are used
const serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
};
const newLanguageClient: LanguageClientConstructor = (id: string, name: string, clientOptions: LanguageClientOptions) => {
return new LanguageClient(id, name, serverOptions, clientOptions);
};
startClient(context, newLanguageClient, { http: getHTTPRequestService(), telemetry });
}
export function deactivate(): Promise<any> {
return telemetry ? telemetry.dispose() : Promise.resolve(null);
}
interface IPackageInfo {
name: string;
version: string;
aiKey: string;
main: string;
}
function getPackageInfo(context: ExtensionContext): IPackageInfo {
const location = context.asAbsolutePath('./package.json');
try {
return JSON.parse(fs.readFileSync(location).toString());
} catch (e) {
console.log(`Problems reading ${location}: ${e}`);
return { name: '', version: '', aiKey: '', main: '' };
}
}
function getHTTPRequestService(): RequestService {
return {
getContent(uri: string, _encoding?: string) {
const headers = { 'Accept-Encoding': 'gzip, deflate' };
return xhr({ url: uri, followRedirects: 5, headers }).then(response => {
return response.responseText;
}, (error: XHRResponse) => {
return Promise.reject(error.responseText || getErrorStatusDescription(error.status) || error.toString());
});
}
};
}

View File

@@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Uri } from 'vscode';
export interface RequestService {
getContent(uri: string, encoding?: string): Thenable<string>;
}
export function getScheme(uri: string) {
return uri.substr(0, uri.indexOf(':'));
}
export function dirname(uri: string) {
const lastIndexOfSlash = uri.lastIndexOf('/');
return lastIndexOfSlash !== -1 ? uri.substr(0, lastIndexOfSlash) : '';
}
export function basename(uri: string) {
const lastIndexOfSlash = uri.lastIndexOf('/');
return uri.substr(lastIndexOfSlash + 1);
}
const Slash = '/'.charCodeAt(0);
const Dot = '.'.charCodeAt(0);
export function isAbsolutePath(path: string) {
return path.charCodeAt(0) === Slash;
}
export function resolvePath(uri: Uri, path: string): Uri {
if (isAbsolutePath(path)) {
return uri.with({ path: normalizePath(path.split('/')) });
}
return joinPath(uri, path);
}
export function normalizePath(parts: string[]): string {
const newParts: string[] = [];
for (const part of parts) {
if (part.length === 0 || part.length === 1 && part.charCodeAt(0) === Dot) {
// ignore
} else if (part.length === 2 && part.charCodeAt(0) === Dot && part.charCodeAt(1) === Dot) {
newParts.pop();
} else {
newParts.push(part);
}
}
if (parts.length > 1 && parts[parts.length - 1].length === 0) {
newParts.push('');
}
let res = newParts.join('/');
if (parts[0].length === 0) {
res = '/' + res;
}
return res;
}
export function joinPath(uri: Uri, ...paths: string[]): Uri {
const parts = uri.path.split('/');
for (let path of paths) {
parts.push(...path.split('/'));
}
return uri.with({ path: normalizePath(parts) });
}