Merge from vscode merge-base (#22780)

* Revert "Revert "Merge from vscode merge-base (#22769)" (#22779)"

This reverts commit 47a1745180.

* Fix notebook download task

* Remove done call from extensions-ci
This commit is contained in:
Karl Burtram
2023-04-19 21:48:46 -07:00
committed by GitHub
parent decbe8dded
commit e7d3d047ec
2389 changed files with 92155 additions and 42602 deletions

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ExtensionContext, Uri } from 'vscode';
import { LanguageClientOptions } from 'vscode-languageclient';
import { BaseLanguageClient, LanguageClientOptions } from 'vscode-languageclient';
import { startClient, LanguageClientConstructor, SchemaRequestService } from '../jsonClient';
import { LanguageClient } from 'vscode-languageclient/browser';
@@ -14,8 +14,10 @@ declare const Worker: {
declare function fetch(uri: string, options: any): any;
let client: BaseLanguageClient | undefined;
// this method is called when vs code is activated
export function activate(context: ExtensionContext) {
export async function activate(context: ExtensionContext) {
const serverMain = Uri.joinPath(context.extensionUri, 'server/dist/browser/jsonServerMain.js');
try {
const worker = new Worker(serverMain.toString());
@@ -32,9 +34,16 @@ export function activate(context: ExtensionContext) {
}
};
startClient(context, newLanguageClient, { schemaRequests });
client = await startClient(context, newLanguageClient, { schemaRequests });
} catch (e) {
console.log(e);
}
}
export async function deactivate(): Promise<void> {
if (client) {
await client.stop();
client = undefined;
}
}

View File

@@ -9,18 +9,19 @@ const localize = nls.loadMessageBundle();
export type JSONLanguageStatus = { schemas: string[] };
import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext, Hover, MarkdownString,
workspace, window, languages, commands, ExtensionContext, extensions, Uri, ColorInformation,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken, FoldingRange,
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext, Hover, MarkdownString, FoldingContext, DocumentSymbol, SymbolInformation
} from 'vscode';
import {
LanguageClientOptions, RequestType, NotificationType,
DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams,
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, ProvideHoverSignature, CommonLanguageClient
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, ProvideHoverSignature, BaseLanguageClient, ProvideFoldingRangeSignature, ProvideDocumentSymbolsSignature, ProvideDocumentColorsSignature
} from 'vscode-languageclient';
import { hash } from './utils/hash';
import { createLanguageStatusItem } from './languageStatus';
import { createDocumentColorsLimitItem, createDocumentSymbolsLimitItem, createFoldingRangeLimitItem, createLanguageStatusItem, createLimitStatusItem } from './languageStatus';
namespace VSCodeContentRequest {
export const type: RequestType<string, string, any> = new RequestType('vscode/content');
@@ -52,14 +53,11 @@ namespace SchemaAssociationNotification {
export const type: NotificationType<ISchemaAssociations | ISchemaAssociation[]> = new NotificationType('json/schemaAssociations');
}
namespace ResultLimitReachedNotification {
export const type: NotificationType<string> = new NotificationType('json/resultLimitReached');
}
interface Settings {
type Settings = {
json?: {
schemas?: JSONSchemaSettings[];
format?: { enable?: boolean };
keepLines?: { enable?: boolean };
validate?: { enable?: boolean };
resultLimit?: number;
};
@@ -67,25 +65,22 @@ interface Settings {
proxy?: string;
proxyStrictSSL?: boolean;
};
}
};
export interface JSONSchemaSettings {
export type JSONSchemaSettings = {
fileMatch?: string[];
url?: string;
schema?: any;
}
};
namespace SettingIds {
export namespace SettingIds {
export const enableFormatter = 'json.format.enable';
export const enableKeepLines = 'json.format.keepLines';
export const enableValidation = 'json.validate.enable';
export const enableSchemaDownload = 'json.schemaDownload.enable';
export const maxItemsComputed = 'json.maxItemsComputed';
}
namespace StorageIds {
export const maxItemsExceededInformation = 'json.maxItemsExceededInformation';
}
export interface TelemetryReporter {
sendTelemetryEvent(eventName: string, properties?: {
[key: string]: string;
@@ -94,7 +89,7 @@ export interface TelemetryReporter {
}): void;
}
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => CommonLanguageClient;
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => BaseLanguageClient;
export interface Runtime {
schemaRequests: SchemaRequestService;
@@ -108,7 +103,9 @@ export interface SchemaRequestService {
export const languageServerDescription = localize('jsonserver.name', 'JSON Language Server');
export function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime) {
let resultLimit = 5000;
export async function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime): Promise<BaseLanguageClient> {
const toDispose = context.subscriptions;
@@ -126,6 +123,11 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
let isClientReady = false;
const foldingRangeLimitStatusBarItem = createLimitStatusItem((limit: number) => createFoldingRangeLimitItem(documentSelector, SettingIds.maxItemsComputed, limit));
const documentSymbolsLimitStatusbarItem = createLimitStatusItem((limit: number) => createDocumentSymbolsLimitItem(documentSelector, SettingIds.maxItemsComputed, limit));
const documentColorsLimitStatusbarItem = createLimitStatusItem((limit: number) => createDocumentColorsLimitItem(documentSelector, SettingIds.maxItemsComputed, limit));
toDispose.push(foldingRangeLimitStatusBarItem, documentSymbolsLimitStatusbarItem, documentColorsLimitStatusbarItem);
toDispose.push(commands.registerCommand('json.clearCache', async () => {
if (isClientReady && runtime.schemaRequests.clearCache) {
const cachedSchemas = await runtime.schemaRequests.clearCache();
@@ -210,6 +212,60 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
return r.then(updateHover);
}
return updateHover(r);
},
provideFoldingRanges(document: TextDocument, context: FoldingContext, token: CancellationToken, next: ProvideFoldingRangeSignature) {
function checkLimit(r: FoldingRange[] | null | undefined): FoldingRange[] | null | undefined {
if (Array.isArray(r) && r.length > resultLimit) {
r.length = resultLimit; // truncate
foldingRangeLimitStatusBarItem.update(document, resultLimit);
} else {
foldingRangeLimitStatusBarItem.update(document, false);
}
return r;
}
const r = next(document, context, token);
if (isThenable<FoldingRange[] | null | undefined>(r)) {
return r.then(checkLimit);
}
return checkLimit(r);
},
provideDocumentColors(document: TextDocument, token: CancellationToken, next: ProvideDocumentColorsSignature) {
function checkLimit(r: ColorInformation[] | null | undefined): ColorInformation[] | null | undefined {
if (Array.isArray(r) && r.length > resultLimit) {
r.length = resultLimit; // truncate
documentColorsLimitStatusbarItem.update(document, resultLimit);
} else {
documentColorsLimitStatusbarItem.update(document, false);
}
return r;
}
const r = next(document, token);
if (isThenable<ColorInformation[] | null | undefined>(r)) {
return r.then(checkLimit);
}
return checkLimit(r);
},
provideDocumentSymbols(document: TextDocument, token: CancellationToken, next: ProvideDocumentSymbolsSignature) {
type T = SymbolInformation[] | DocumentSymbol[];
function countDocumentSymbols(symbols: DocumentSymbol[]): number {
return symbols.reduce((previousValue, s) => previousValue + 1 + countDocumentSymbols(s.children), 0);
}
function isDocumentSymbol(r: T): r is DocumentSymbol[] {
return r[0] instanceof DocumentSymbol;
}
function checkLimit(r: T | null | undefined): T | null | undefined {
if (Array.isArray(r) && (isDocumentSymbol(r) ? countDocumentSymbols(r) : r.length) > resultLimit) {
documentSymbolsLimitStatusbarItem.update(document, resultLimit);
} else {
documentSymbolsLimitStatusbarItem.update(document, false);
}
return r;
}
const r = next(document, token);
if (isThenable<T | undefined | null>(r)) {
return r.then(checkLimit);
}
return checkLimit(r);
}
}
};
@@ -218,176 +274,162 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
const client = newLanguageClient('json', languageServerDescription, clientOptions);
client.registerProposedFeatures();
const disposable = client.start();
toDispose.push(disposable);
client.onReady().then(() => {
isClientReady = true;
const schemaDocuments: { [uri: string]: boolean } = {};
const schemaDocuments: { [uri: string]: boolean } = {};
// handle content request
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
const uri = Uri.parse(uriPath);
if (uri.scheme === 'untitled') {
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(new ResponseError(2, error.toString()));
});
} else if (schemaDownloadEnabled) {
if (runtime.telemetry && uri.authority === 'schema.management.azure.com') {
/* __GDPR__
"json.schema" : {
"schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
runtime.telemetry.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
}
return runtime.schemaRequests.getContent(uriPath).catch(e => {
return Promise.reject(new ResponseError(4, e.toString()));
});
} else {
return Promise.reject(new ResponseError(1, localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload)));
}
});
const handleContentChange = (uriString: string) => {
if (schemaDocuments[uriString]) {
client.sendNotification(SchemaContentChangeNotification.type, uriString);
return true;
}
return false;
};
const handleActiveEditorChange = (activeEditor?: TextEditor) => {
if (!activeEditor) {
return;
}
const activeDocUri = activeEditor.document.uri.toString();
if (activeDocUri && fileSchemaErrors.has(activeDocUri)) {
schemaResolutionErrorStatusBarItem.show();
} else {
schemaResolutionErrorStatusBarItem.hide();
}
};
toDispose.push(workspace.onDidChangeTextDocument(e => handleContentChange(e.document.uri.toString())));
toDispose.push(workspace.onDidCloseTextDocument(d => {
const uriString = d.uri.toString();
if (handleContentChange(uriString)) {
delete schemaDocuments[uriString];
}
fileSchemaErrors.delete(uriString);
}));
toDispose.push(window.onDidChangeActiveTextEditor(handleActiveEditorChange));
const handleRetryResolveSchemaCommand = () => {
if (window.activeTextEditor) {
schemaResolutionErrorStatusBarItem.text = '$(watch)';
const activeDocUri = window.activeTextEditor.document.uri.toString();
client.sendRequest(ForceValidateRequest.type, activeDocUri).then((diagnostics) => {
const schemaErrorIndex = diagnostics.findIndex(isSchemaResolveError);
if (schemaErrorIndex !== -1) {
// Show schema resolution errors in status bar only; ref: #51032
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
fileSchemaErrors.set(activeDocUri, schemaResolveDiagnostic.message);
} else {
schemaResolutionErrorStatusBarItem.hide();
}
schemaResolutionErrorStatusBarItem.text = '$(alert)';
});
}
};
toDispose.push(commands.registerCommand('_json.retryResolveSchema', handleRetryResolveSchemaCommand));
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
toDispose.push(extensions.onDidChange(_ => {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
}));
// manually register / deregister format provider based on the `json.format.enable` setting avoiding issues with late registration. See #71652.
updateFormatterRegistration();
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
updateSchemaDownloadSetting();
toDispose.push(workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(SettingIds.enableFormatter)) {
updateFormatterRegistration();
} else if (e.affectsConfiguration(SettingIds.enableSchemaDownload)) {
updateSchemaDownloadSetting();
}
}));
client.onNotification(ResultLimitReachedNotification.type, async message => {
const shouldPrompt = context.globalState.get<boolean>(StorageIds.maxItemsExceededInformation) !== false;
if (shouldPrompt) {
const ok = localize('ok', "OK");
const openSettings = localize('goToSetting', 'Open Settings');
const neverAgain = localize('yes never again', "Don't Show Again");
const pick = await window.showInformationMessage(`${message}\n${localize('configureLimit', 'Use setting \'{0}\' to configure the limit.', SettingIds.maxItemsComputed)}`, ok, openSettings, neverAgain);
if (pick === neverAgain) {
await context.globalState.update(StorageIds.maxItemsExceededInformation, false);
} else if (pick === openSettings) {
await commands.executeCommand('workbench.action.openSettings', SettingIds.maxItemsComputed);
}
}
});
toDispose.push(createLanguageStatusItem(documentSelector, (uri: string) => client.sendRequest(LanguageStatusRequest.type, uri)));
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
if (!formatEnabled && rangeFormatting) {
rangeFormatting.dispose();
rangeFormatting = undefined;
} else if (formatEnabled && !rangeFormatting) {
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
const filesConfig = workspace.getConfiguration('files', document);
const fileFormattingOptions = {
trimTrailingWhitespace: filesConfig.get<boolean>('trimTrailingWhitespace'),
trimFinalNewlines: filesConfig.get<boolean>('trimFinalNewlines'),
insertFinalNewline: filesConfig.get<boolean>('insertFinalNewline'),
};
const params: DocumentRangeFormattingParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
range: client.code2ProtocolConverter.asRange(range),
options: client.code2ProtocolConverter.asFormattingOptions(options, fileFormattingOptions)
};
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
client.protocol2CodeConverter.asTextEdits,
(error) => {
client.handleFailedRequest(DocumentRangeFormattingRequest.type, error, []);
return Promise.resolve([]);
}
);
}
});
}
// handle content request
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
const uri = Uri.parse(uriPath);
if (uri.scheme === 'untitled') {
return Promise.reject(new ResponseError(3, localize('untitled.schema', 'Unable to load {0}', uri.toString())));
}
function updateSchemaDownloadSetting() {
schemaDownloadEnabled = workspace.getConfiguration().get(SettingIds.enableSchemaDownload) !== false;
if (schemaDownloadEnabled) {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema. Click to retry.');
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
handleRetryResolveSchemaCommand();
} else {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionDisabledMessage', 'Downloading schemas is disabled. Click to configure.');
schemaResolutionErrorStatusBarItem.command = { command: 'workbench.action.openSettings', arguments: [SettingIds.enableSchemaDownload], title: '' };
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
return workspace.openTextDocument(uri).then(doc => {
schemaDocuments[uri.toString()] = true;
return doc.getText();
}, error => {
return Promise.reject(new ResponseError(2, error.toString()));
});
} else if (schemaDownloadEnabled) {
if (runtime.telemetry && uri.authority === 'schema.management.azure.com') {
/* __GDPR__
"json.schema" : {
"owner": "aeschli",
"comment": "Measure the use of the Azure resource manager schemas",
"schemaURL" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The azure schema URL that was requested." }
}
*/
runtime.telemetry.sendTelemetryEvent('json.schema', { schemaURL: uriPath });
}
return runtime.schemaRequests.getContent(uriPath).catch(e => {
return Promise.reject(new ResponseError(4, e.toString()));
});
} else {
return Promise.reject(new ResponseError(1, localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload)));
}
});
await client.start();
isClientReady = true;
const handleContentChange = (uriString: string) => {
if (schemaDocuments[uriString]) {
client.sendNotification(SchemaContentChangeNotification.type, uriString);
return true;
}
return false;
};
const handleActiveEditorChange = (activeEditor?: TextEditor) => {
if (!activeEditor) {
return;
}
const activeDocUri = activeEditor.document.uri.toString();
if (activeDocUri && fileSchemaErrors.has(activeDocUri)) {
schemaResolutionErrorStatusBarItem.show();
} else {
schemaResolutionErrorStatusBarItem.hide();
}
};
toDispose.push(workspace.onDidChangeTextDocument(e => handleContentChange(e.document.uri.toString())));
toDispose.push(workspace.onDidCloseTextDocument(d => {
const uriString = d.uri.toString();
if (handleContentChange(uriString)) {
delete schemaDocuments[uriString];
}
fileSchemaErrors.delete(uriString);
}));
toDispose.push(window.onDidChangeActiveTextEditor(handleActiveEditorChange));
const handleRetryResolveSchemaCommand = () => {
if (window.activeTextEditor) {
schemaResolutionErrorStatusBarItem.text = '$(watch)';
const activeDocUri = window.activeTextEditor.document.uri.toString();
client.sendRequest(ForceValidateRequest.type, activeDocUri).then((diagnostics) => {
const schemaErrorIndex = diagnostics.findIndex(isSchemaResolveError);
if (schemaErrorIndex !== -1) {
// Show schema resolution errors in status bar only; ref: #51032
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
fileSchemaErrors.set(activeDocUri, schemaResolveDiagnostic.message);
} else {
schemaResolutionErrorStatusBarItem.hide();
}
schemaResolutionErrorStatusBarItem.text = '$(alert)';
});
}
};
toDispose.push(commands.registerCommand('_json.retryResolveSchema', handleRetryResolveSchemaCommand));
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
toDispose.push(extensions.onDidChange(_ => {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
}));
// manually register / deregister format provider based on the `json.format.enable` setting avoiding issues with late registration. See #71652.
updateFormatterRegistration();
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
updateSchemaDownloadSetting();
toDispose.push(workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(SettingIds.enableFormatter)) {
updateFormatterRegistration();
} else if (e.affectsConfiguration(SettingIds.enableSchemaDownload)) {
updateSchemaDownloadSetting();
}
}));
toDispose.push(createLanguageStatusItem(documentSelector, (uri: string) => client.sendRequest(LanguageStatusRequest.type, uri)));
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
if (!formatEnabled && rangeFormatting) {
rangeFormatting.dispose();
rangeFormatting = undefined;
} else if (formatEnabled && !rangeFormatting) {
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
const filesConfig = workspace.getConfiguration('files', document);
const fileFormattingOptions = {
trimTrailingWhitespace: filesConfig.get<boolean>('trimTrailingWhitespace'),
trimFinalNewlines: filesConfig.get<boolean>('trimFinalNewlines'),
insertFinalNewline: filesConfig.get<boolean>('insertFinalNewline'),
};
const params: DocumentRangeFormattingParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
range: client.code2ProtocolConverter.asRange(range),
options: client.code2ProtocolConverter.asFormattingOptions(options, fileFormattingOptions)
};
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
client.protocol2CodeConverter.asTextEdits,
(error) => {
client.handleFailedRequest(DocumentRangeFormattingRequest.type, undefined, error, []);
return Promise.resolve([]);
}
);
}
});
}
}
function updateSchemaDownloadSetting() {
schemaDownloadEnabled = workspace.getConfiguration().get(SettingIds.enableSchemaDownload) !== false;
if (schemaDownloadEnabled) {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema. Click to retry.');
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
handleRetryResolveSchemaCommand();
} else {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionDisabledMessage', 'Downloading schemas is disabled. Click to configure.');
schemaResolutionErrorStatusBarItem.command = { command: 'workbench.action.openSettings', arguments: [SettingIds.enableSchemaDownload], title: '' };
}
}
return client;
}
function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[] {
@@ -430,7 +472,7 @@ function getSettings(): Settings {
const configuration = workspace.getConfiguration();
const httpSettings = workspace.getConfiguration('http');
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get(SettingIds.maxItemsComputed)))) || 5000;
resultLimit = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get(SettingIds.maxItemsComputed)))) || 5000;
const settings: Settings = {
http: {
@@ -440,8 +482,9 @@ function getSettings(): Settings {
json: {
validate: { enable: configuration.get(SettingIds.enableValidation) },
format: { enable: configuration.get(SettingIds.enableFormatter) },
keepLines: { enable: configuration.get(SettingIds.enableKeepLines) },
schemas: [],
resultLimit
resultLimit: resultLimit + 1 // ask for one more so we can detect if the limit has been exceeded
}
};
const schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);

View File

@@ -3,7 +3,11 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { window, languages, Uri, LanguageStatusSeverity, Disposable, commands, QuickPickItem, extensions, workspace, Extension, WorkspaceFolder, QuickPickItemKind, ThemeIcon } from 'vscode';
import {
window, languages, Uri, Disposable, commands, QuickPickItem,
extensions, workspace, Extension, WorkspaceFolder, QuickPickItemKind,
ThemeIcon, TextDocument, LanguageStatusSeverity
} from 'vscode';
import { JSONLanguageStatus, JSONSchemaSettings } from './jsonClient';
import * as nls from 'vscode-nls';
@@ -187,13 +191,13 @@ export function createLanguageStatusItem(documentSelector: string[], statusReque
statusItem.detail = undefined;
if (schemas.length === 0) {
statusItem.text = localize('status.noSchema.short', "No Schema Validation");
statusItem.detail = localize('status.noSchema', 'No JSON schema configured.');
statusItem.detail = localize('status.noSchema', 'no JSON schema configured');
} else if (schemas.length === 1) {
statusItem.text = localize('status.withSchema.short', "Schema Validated");
statusItem.detail = localize('status.singleSchema', 'JSON schema configured.');
statusItem.detail = localize('status.singleSchema', 'JSON schema configured');
} else {
statusItem.text = localize('status.withSchemas.short', "Schema Validated");
statusItem.detail = localize('status.multipleSchema', 'Multiple JSON schemas configured.');
statusItem.detail = localize('status.multipleSchema', 'multiple JSON schemas configured');
}
statusItem.command = {
command: '_json.showAssociatedSchemaList',
@@ -217,3 +221,85 @@ export function createLanguageStatusItem(documentSelector: string[], statusReque
return Disposable.from(statusItem, activeEditorListener, showSchemasCommand);
}
export function createLimitStatusItem(newItem: (limit: number) => Disposable) {
let statusItem: Disposable | undefined;
const activeLimits: Map<TextDocument, number> = new Map();
const toDispose: Disposable[] = [];
toDispose.push(window.onDidChangeActiveTextEditor(textEditor => {
statusItem?.dispose();
statusItem = undefined;
const doc = textEditor?.document;
if (doc) {
const limit = activeLimits.get(doc);
if (limit !== undefined) {
statusItem = newItem(limit);
}
}
}));
toDispose.push(workspace.onDidCloseTextDocument(document => {
activeLimits.delete(document);
}));
function update(document: TextDocument, limitApplied: number | false) {
if (limitApplied === false) {
activeLimits.delete(document);
if (statusItem && document === window.activeTextEditor?.document) {
statusItem.dispose();
statusItem = undefined;
}
} else {
activeLimits.set(document, limitApplied);
if (document === window.activeTextEditor?.document) {
if (!statusItem || limitApplied !== activeLimits.get(document)) {
statusItem?.dispose();
statusItem = newItem(limitApplied);
}
}
}
}
return {
update,
dispose() {
statusItem?.dispose();
toDispose.forEach(d => d.dispose());
toDispose.length = 0;
statusItem = undefined;
activeLimits.clear();
}
};
}
const openSettingsCommand = 'workbench.action.openSettings';
const configureSettingsLabel = localize('status.button.configure', "Configure");
export function createFoldingRangeLimitItem(documentSelector: string[], settingId: string, limit: number): Disposable {
const statusItem = languages.createLanguageStatusItem('json.foldingRangesStatus', documentSelector);
statusItem.name = localize('foldingRangesStatusItem.name', "JSON Folding Status");
statusItem.severity = LanguageStatusSeverity.Warning;
statusItem.text = localize('status.limitedFoldingRanges.short', "Folding Ranges Limited");
statusItem.detail = localize('status.limitedFoldingRanges.details', 'only {0} folding ranges shown', limit);
statusItem.command = { command: openSettingsCommand, arguments: [settingId], title: configureSettingsLabel };
return Disposable.from(statusItem);
}
export function createDocumentSymbolsLimitItem(documentSelector: string[], settingId: string, limit: number): Disposable {
const statusItem = languages.createLanguageStatusItem('json.documentSymbolsStatus', documentSelector);
statusItem.name = localize('documentSymbolsStatusItem.name', "JSON Outline Status");
statusItem.severity = LanguageStatusSeverity.Warning;
statusItem.text = localize('status.limitedDocumentSymbols.short', "Outline Limited");
statusItem.detail = localize('status.limitedDocumentSymbols.details', 'only {0} document symbols shown', limit);
statusItem.command = { command: openSettingsCommand, arguments: [settingId], title: configureSettingsLabel };
return Disposable.from(statusItem);
}
export function createDocumentColorsLimitItem(documentSelector: string[], settingId: string, limit: number): Disposable {
const statusItem = languages.createLanguageStatusItem('json.documentColorsStatus', documentSelector);
statusItem.name = localize('documentColorsStatusItem.name', "JSON Color Symbol Status");
statusItem.severity = LanguageStatusSeverity.Warning;
statusItem.text = localize('status.limitedDocumentColors.short', "Color Symbols Limited");
statusItem.detail = localize('status.limitedDocumentColors.details', 'only {0} color decorators shown', limit);
statusItem.command = { command: openSettingsCommand, arguments: [settingId], title: configureSettingsLabel };
return Disposable.from(statusItem);
}

View File

@@ -5,7 +5,7 @@
import { ExtensionContext, OutputChannel, window, workspace } from 'vscode';
import { startClient, LanguageClientConstructor, SchemaRequestService, languageServerDescription } from '../jsonClient';
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient } from 'vscode-languageclient/node';
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient, BaseLanguageClient } from 'vscode-languageclient/node';
import { promises as fs } from 'fs';
import * as path from 'path';
@@ -15,6 +15,7 @@ import TelemetryReporter from '@vscode/extension-telemetry';
import { JSONSchemaCache } from './schemaCache';
let telemetry: TelemetryReporter | undefined;
let client: BaseLanguageClient | undefined;
// this method is called when vs code is activated
export async function activate(context: ExtensionContext) {
@@ -45,11 +46,15 @@ export async function activate(context: ExtensionContext) {
const schemaRequests = await getSchemaRequestService(context, log);
startClient(context, newLanguageClient, { schemaRequests, telemetry });
client = await startClient(context, newLanguageClient, { schemaRequests, telemetry });
}
export function deactivate(): Promise<any> {
return telemetry ? telemetry.dispose() : Promise.resolve(null);
export async function deactivate(): Promise<any> {
if (client) {
await client.stop();
client = undefined;
}
telemetry?.dispose();
}
interface IPackageInfo {