[json] Adapt language status indicator. Fixes #137288

This commit is contained in:
Martin Aeschlimann 2021-11-18 14:46:54 +01:00
parent 8c64e1ec31
commit 6651f8ab43
No known key found for this signature in database
GPG key ID: 2609A01E695523E3
7 changed files with 121 additions and 7 deletions

View file

@ -6,6 +6,8 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export type JSONLanguageStatus = { schemas: string[] };
import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
@ -19,6 +21,7 @@ import {
import { hash } from './utils/hash';
import { RequestService, joinPath } from './requests';
import { createLanguageStatusItem } from './languageStatus';
namespace VSCodeContentRequest {
export const type: RequestType<string, string, any> = new RequestType('vscode/content');
@ -32,6 +35,11 @@ namespace ForceValidateRequest {
export const type: RequestType<string, Diagnostic[], any> = new RequestType('json/validate');
}
namespace LanguageStatusRequest {
export const type: RequestType<string, JSONLanguageStatus, any> = new RequestType('json/languageStatus');
}
export interface ISchemaAssociations {
[pattern: string]: string[];
}
@ -314,6 +322,8 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
}
});
toDispose.push(createLanguageStatusItem(documentSelector, (uri: string) => client.sendRequest(LanguageStatusRequest.type, uri)));
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
if (!formatEnabled && rangeFormatting) {

View file

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { window, languages, Uri, LanguageStatusSeverity, Disposable, commands, QuickPickItem } from 'vscode';
import { JSONLanguageStatus } from './jsonClient';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
export function createLanguageStatusItem(documentSelector: string[], statusRequest: (uri: string) => Promise<JSONLanguageStatus>): Disposable {
const statusItem = languages.createLanguageStatusItem('json.projectStatus', documentSelector);
statusItem.name = localize('statusItem.name', "JSON Validation Status");
statusItem.severity = LanguageStatusSeverity.Information;
const showSchemasCommand = commands.registerCommand('json.showSchemasCommand', arg => {
const items = arg.schemas.sort().map((a: string) => ({ label: a }));
const quickPick = window.createQuickPick<QuickPickItem>();
quickPick.title = localize('schemaPicker.title', 'Associated JSON Schemas');
quickPick.placeholder = localize('schemaPicker.placeholder', 'Select the schema to open');
quickPick.items = items;
quickPick.show();
quickPick.onDidAccept(() => {
const selectedSchema = quickPick.selectedItems[0].label;
commands.executeCommand('vscode.open', Uri.parse(selectedSchema));
quickPick.dispose();
});
});
const activeEditorListener = window.onDidChangeActiveTextEditor(() => {
updateLanguageStatus();
});
async function updateLanguageStatus() {
const document = window.activeTextEditor?.document;
if (document && documentSelector.indexOf(document.languageId) !== -1) {
try {
statusItem.text = '$(loading~spin)';
statusItem.detail = localize('pending.detail', 'Loading JSON info');
statusItem.command = undefined;
const schemas = (await statusRequest(document.uri.toString())).schemas;
statusItem.detail = undefined;
if (schemas.length === 0) {
statusItem.text = localize('status.noSchema', 'Validated without JSON schema');
} else if (schemas.length === 1) {
statusItem.text = localize('status.singleSchema', 'Validated with JSON schema');
statusItem.command = {
command: 'vscode.open',
title: localize('status.openSchemaLink', 'Open Schema'),
tooltip: schemas[0],
arguments: [Uri.parse(schemas[0])]
};
} else {
statusItem.text = localize('status.multipleSchema', 'Validated with multiple JSON schemas');
statusItem.command = {
command: 'json.showSchemasCommand',
title: localize('status.openSchemasLink', 'Show Schemas'),
arguments: [{ schemas }]
};
}
} catch (e) {
statusItem.text = localize('status.error', 'Unable to compute used schemas');
statusItem.detail = undefined;
statusItem.command = undefined;
console.log(e);
}
} else {
statusItem.text = localize('status.notJSON', 'Not a JSON editor');
statusItem.detail = undefined;
statusItem.command = undefined;
}
}
updateLanguageStatus();
return Disposable.from(statusItem, activeEditorListener, showSchemasCommand);
}

View file

@ -5,6 +5,7 @@
},
"include": [
"src/**/*",
"../../../src/vscode-dts/vscode.d.ts"
"../../../src/vscode-dts/vscode.d.ts",
"../../../src/vscode-dts/vscode.proposed.languageStatus.d.ts",
]
}

View file

@ -12,7 +12,8 @@
"icon": "icons/json.png",
"activationEvents": [
"onLanguage:json",
"onLanguage:jsonc"
"onLanguage:jsonc",
"onCommand:json.showSchemas"
],
"main": "./client/out/node/jsonClientMain",
"browser": "./client/dist/browser/jsonClientMain",
@ -22,6 +23,9 @@
"supported": true
}
},
"enabledApiProposals": [
"languageStatus"
],
"scripts": {
"compile": "npx gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
"watch": "npx gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",

View file

@ -14,7 +14,7 @@
"dependencies": {
"jsonc-parser": "^3.0.0",
"request-light": "^0.5.4",
"vscode-json-languageservice": "^4.1.10",
"vscode-json-languageservice": "^4.2.0-next.1",
"vscode-languageserver": "^7.0.0",
"vscode-uri": "^3.0.2"
},

View file

@ -16,6 +16,8 @@ import { RequestService, basename, resolvePath } from './requests';
type ISchemaAssociations = Record<string, string[]>;
type JSONLanguageStatus = { schemas: string[] };
namespace SchemaAssociationNotification {
export const type: NotificationType<ISchemaAssociations | SchemaConfiguration[]> = new NotificationType('json/schemaAssociations');
}
@ -36,6 +38,10 @@ namespace ForceValidateRequest {
export const type: RequestType<string, Diagnostic[], any> = new RequestType('json/validate');
}
namespace LanguageStatusRequest {
export const type: RequestType<string, JSONLanguageStatus, any> = new RequestType('json/languageStatus');
}
const workspaceContext = {
resolveRelativePath: (relativePath: string, resource: string) => {
@ -277,6 +283,16 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
});
});
connection.onRequest(LanguageStatusRequest.type, async uri => {
const document = documents.get(uri);
if (document) {
const jsonDocument = getJSONDocument(document);
return languageService.getLanguageStatus(document, jsonDocument);
} else {
return { schemas: [] };
}
});
function updateConfiguration() {
const languageSettings = {
validate: true,

View file

@ -22,10 +22,10 @@ request-light@^0.5.4:
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.5.4.tgz#497a98c6d8ae49536417a5e2d7f383b934f3e38c"
integrity sha512-t3566CMweOFlUk7Y1DJMu5OrtpoZEb6aSTsLQVT3wtrIEJ5NhcY9G/Oqxvjllzl4a15zXfFlcr9q40LbLVQJqw==
vscode-json-languageservice@^4.1.10:
version "4.1.10"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.10.tgz#5d5729fc4f3e02f41599e0104523a1877c25f0fb"
integrity sha512-IHliMEEYSY0tJjJt0ECb8ESx/nRXpoy9kN42WVQXgaqGyizFAf3jibSiezDQTrrY7f3kywXggCU+kkJEM+OLZQ==
vscode-json-languageservice@^4.2.0-next.1:
version "4.2.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.2.0-next.1.tgz#31a8c3be04c87d5aa593c11b98d84258b173a22f"
integrity sha512-aQvkkuZpeSPv86QLzyMdKTCgvXR+qSO39nSgj/XGaOcuHmTt7vMZB7ymYGGkQ4cAaQdHs/2G6a479LQybIGSbg==
dependencies:
jsonc-parser "^3.0.0"
vscode-languageserver-textdocument "^1.0.1"