Skip to content

Commit 785eb08

Browse files
committed
jsonValidation takes an array for fileMatch
1 parent 55c2dc5 commit 785eb08

5 files changed

Lines changed: 54 additions & 38 deletions

File tree

extensions/json-language-features/client/src/jsonMain.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,13 @@ export interface ISchemaAssociations {
4040
[pattern: string]: string[];
4141
}
4242

43+
export interface ISchemaAssociation {
44+
fileMatch: string[];
45+
uri: string;
46+
}
47+
4348
namespace SchemaAssociationNotification {
44-
export const type: NotificationType<ISchemaAssociations, any> = new NotificationType('json/schemaAssociations');
49+
export const type: NotificationType<ISchemaAssociations | ISchemaAssociation[], any> = new NotificationType('json/schemaAssociations');
4550
}
4651

4752
namespace ResultLimitReachedNotification {
@@ -264,10 +269,10 @@ export function activate(context: ExtensionContext) {
264269

265270
toDispose.push(commands.registerCommand('_json.retryResolveSchema', handleRetryResolveSchemaCommand));
266271

267-
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
272+
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
268273

269274
extensions.onDidChange(_ => {
270-
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
275+
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
271276
});
272277

273278
// manually register / deregister format provider based on the `html.format.enable` setting avoiding issues with late registration. See #71652.
@@ -324,32 +329,30 @@ export function deactivate(): Promise<any> {
324329
return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null);
325330
}
326331

327-
function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
328-
const associations: ISchemaAssociations = {};
332+
function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[] {
333+
const associations: ISchemaAssociation[] = [];
329334
extensions.all.forEach(extension => {
330335
const packageJSON = extension.packageJSON;
331336
if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation) {
332337
const jsonValidation = packageJSON.contributes.jsonValidation;
333338
if (Array.isArray(jsonValidation)) {
334339
jsonValidation.forEach(jv => {
335340
let { fileMatch, url } = jv;
336-
if (fileMatch && url) {
337-
if (url[0] === '.' && url[1] === '/') {
338-
url = Uri.file(path.join(extension.extensionPath, url)).toString();
339-
}
340-
if (fileMatch[0] === '%') {
341-
fileMatch = fileMatch.replace(/%APP_SETTINGS_HOME%/, '/User');
342-
fileMatch = fileMatch.replace(/%MACHINE_SETTINGS_HOME%/, '/Machine');
343-
fileMatch = fileMatch.replace(/%APP_WORKSPACES_HOME%/, '/Workspaces');
344-
} else if (fileMatch.charAt(0) !== '/' && !fileMatch.match(/\w+:\/\//)) {
345-
fileMatch = '/' + fileMatch;
346-
}
347-
let association = associations[fileMatch];
348-
if (!association) {
349-
association = [];
350-
associations[fileMatch] = association;
351-
}
352-
association.push(url);
341+
if (typeof fileMatch === 'string') {
342+
fileMatch = [fileMatch];
343+
}
344+
if (Array.isArray(fileMatch) && url) {
345+
fileMatch = fileMatch.map(fm => {
346+
if (fm[0] === '%') {
347+
fm = fm.replace(/%APP_SETTINGS_HOME%/, '/User');
348+
fm = fm.replace(/%MACHINE_SETTINGS_HOME%/, '/Machine');
349+
fm = fm.replace(/%APP_WORKSPACES_HOME%/, '/Workspaces');
350+
} else if (!fm.match(/^(\w+:\/\/|\/|!)/)) {
351+
fm = '/' + fm;
352+
}
353+
return fm;
354+
});
355+
associations.push({ fileMatch, uri: url });
353356
}
354357
});
355358
}

extensions/json-language-features/server/src/jsonServerMain.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ interface ISchemaAssociations {
2323
[pattern: string]: string[];
2424
}
2525

26+
interface ISchemaAssociation {
27+
fileMatch: string[];
28+
uri: string;
29+
}
30+
2631
namespace SchemaAssociationNotification {
27-
export const type: NotificationType<ISchemaAssociations, any> = new NotificationType('json/schemaAssociations');
32+
export const type: NotificationType<ISchemaAssociations | ISchemaAssociation[], any> = new NotificationType('json/schemaAssociations');
2833
}
2934

3035
namespace VSCodeContentRequest {
@@ -230,7 +235,7 @@ namespace LimitExceededWarnings {
230235
}
231236

232237
let jsonConfigurationSettings: JSONSchemaSettings[] | undefined = undefined;
233-
let schemaAssociations: ISchemaAssociations | undefined = undefined;
238+
let schemaAssociations: ISchemaAssociations | ISchemaAssociation[] | undefined = undefined;
234239
let formatterRegistration: Thenable<Disposable> | null = null;
235240

236241
// The settings have changed. Is send on server activation as well.
@@ -291,12 +296,16 @@ function updateConfiguration() {
291296
schemas: new Array<SchemaConfiguration>()
292297
};
293298
if (schemaAssociations) {
294-
for (const pattern in schemaAssociations) {
295-
const association = schemaAssociations[pattern];
296-
if (Array.isArray(association)) {
297-
association.forEach(uri => {
298-
languageSettings.schemas.push({ uri, fileMatch: [pattern] });
299-
});
299+
if (Array.isArray(schemaAssociations)) {
300+
Array.prototype.push.apply(languageSettings.schemas, schemaAssociations);
301+
} else {
302+
for (const pattern in schemaAssociations) {
303+
const association = schemaAssociations[pattern];
304+
if (Array.isArray(association)) {
305+
association.forEach(uri => {
306+
languageSettings.schemas.push({ uri, fileMatch: [pattern] });
307+
});
308+
}
300309
}
301310
}
302311
}

src/vs/platform/extensions/common/extensions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface IGrammar {
3838
}
3939

4040
export interface IJSONValidation {
41-
fileMatch: string;
41+
fileMatch: string | string[];
4242
url: string;
4343
}
4444

src/vs/workbench/api/common/jsonValidationExtensionPoint.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import * as nls from 'vs/nls';
77
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
88
import * as strings from 'vs/base/common/strings';
99
import * as resources from 'vs/base/common/resources';
10+
import { isString } from 'vs/base/common/types';
1011

1112
interface IJSONValidationExtensionPoint {
12-
fileMatch: string;
13+
fileMatch: string | string[];
1314
url: string;
1415
}
1516

@@ -25,8 +26,11 @@ const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IJSONVal
2526
defaultSnippets: [{ body: { fileMatch: '${1:file.json}', url: '${2:url}' } }],
2627
properties: {
2728
fileMatch: {
28-
type: 'string',
29-
description: nls.localize('contributes.jsonValidation.fileMatch', 'The file pattern to match, for example "package.json" or "*.launch".'),
29+
type: ['string', 'array'],
30+
description: nls.localize('contributes.jsonValidation.fileMatch', 'The file pattern (or an array of patterns) to match, for example "package.json" or "*.launch". Exclusion patterns start with \'!\''),
31+
items: {
32+
type: ['string']
33+
}
3034
},
3135
url: {
3236
description: nls.localize('contributes.jsonValidation.url', 'A schema URL (\'http:\', \'https:\') or relative path to the extension folder (\'./\').'),
@@ -51,12 +55,12 @@ export class JSONValidationExtensionPoint {
5155
return;
5256
}
5357
extensionValue.forEach(extension => {
54-
if (typeof extension.fileMatch !== 'string') {
55-
collector.error(nls.localize('invalid.fileMatch', "'configuration.jsonValidation.fileMatch' must be defined"));
58+
if (!isString(extension.fileMatch) && !(Array.isArray(extension.fileMatch) && extension.fileMatch.every(isString))) {
59+
collector.error(nls.localize('invalid.fileMatch', "'configuration.jsonValidation.fileMatch' must be defined as a string or an array of strings."));
5660
return;
5761
}
5862
let uri = extension.url;
59-
if (typeof extension.url !== 'string') {
63+
if (!isString(uri)) {
6064
collector.error(nls.localize('invalid.url', "'configuration.jsonValidation.url' must be a URL or relative path"));
6165
return;
6266
}

src/vs/workbench/contrib/extensions/browser/extensionEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ export class ExtensionEditor extends BaseEditor {
12081208
$('th', undefined, localize('schema', "Schema"))
12091209
),
12101210
...contrib.map(v => $('tr', undefined,
1211-
$('td', undefined, $('code', undefined, v.fileMatch)),
1211+
$('td', undefined, $('code', undefined, Array.isArray(v.fileMatch) ? v.fileMatch.join(', ') : v.fileMatch)),
12121212
$('td', undefined, v.url)
12131213
))));
12141214

0 commit comments

Comments
 (0)