Fix JSON schema configuration in multi root workspaces (#173169)

[json] add folderUri to SchemaAssociation and schema setting
This commit is contained in:
Martin Aeschlimann 2023-02-02 22:36:41 +01:00 committed by GitHub
parent 262ab0e7bf
commit bd9ac7a089
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 71 deletions

View file

@ -70,6 +70,7 @@ export type JSONSchemaSettings = {
fileMatch?: string[];
url?: string;
schema?: any;
folderUri?: string;
};
export namespace SettingIds {
@ -472,6 +473,8 @@ function getSettings(): Settings {
jsonFoldingLimit = normalizeLimit(workspace.getConfiguration(SettingIds.editorSection, { languageId: 'json' }).get(SettingIds.foldingMaximumRegions));
jsoncFoldingLimit = normalizeLimit(workspace.getConfiguration(SettingIds.editorSection, { languageId: 'jsonc' }).get(SettingIds.foldingMaximumRegions));
const schemas: JSONSchemaSettings[] = [];
const settings: Settings = {
http: {
proxy: httpSettings.get('proxy'),
@ -481,85 +484,34 @@ function getSettings(): Settings {
validate: { enable: configuration.get(SettingIds.enableValidation) },
format: { enable: configuration.get(SettingIds.enableFormatter) },
keepLines: { enable: configuration.get(SettingIds.enableKeepLines) },
schemas: [],
schemas,
resultLimit: resultLimit + 1, // ask for one more so we can detect if the limit has been exceeded
jsonFoldingLimit: jsonFoldingLimit + 1,
jsoncFoldingLimit: jsoncFoldingLimit + 1
}
};
const schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
const collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], folderUri?: Uri, isMultiRoot?: boolean) => {
let fileMatchPrefix = undefined;
if (folderUri && isMultiRoot) {
fileMatchPrefix = folderUri.toString();
if (fileMatchPrefix[fileMatchPrefix.length - 1] === '/') {
fileMatchPrefix = fileMatchPrefix.substr(0, fileMatchPrefix.length - 1);
}
}
const collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], folderUri?: Uri) => {
for (const setting of schemaSettings) {
const url = getSchemaId(setting, folderUri);
if (!url) {
continue;
}
let schemaSetting = schemaSettingsById[url];
if (!schemaSetting) {
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
settings.json!.schemas!.push(schemaSetting);
}
const fileMatches = setting.fileMatch;
if (Array.isArray(fileMatches)) {
const resultingFileMatches = schemaSetting.fileMatch || [];
schemaSetting.fileMatch = resultingFileMatches;
const addMatch = (pattern: string) => { // filter duplicates
if (resultingFileMatches.indexOf(pattern) === -1) {
resultingFileMatches.push(pattern);
}
};
for (const fileMatch of fileMatches) {
if (fileMatchPrefix) {
if (fileMatch[0] === '/') {
addMatch(fileMatchPrefix + fileMatch);
addMatch(fileMatchPrefix + '/*' + fileMatch);
} else {
addMatch(fileMatchPrefix + '/' + fileMatch);
addMatch(fileMatchPrefix + '/*/' + fileMatch);
}
} else {
addMatch(fileMatch);
}
}
}
if (setting.schema && !schemaSetting.schema) {
schemaSetting.schema = setting.schema;
if (url) {
const schemaSetting: JSONSchemaSettings = { url, fileMatch: setting.fileMatch, folderUri: folderUri?.toString(false), schema: setting.schema };
schemas.push(schemaSetting);
}
}
};
const folders = workspace.workspaceFolders;
// merge global and folder settings. Qualify all file matches with the folder path.
const globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
if (Array.isArray(globalSettings)) {
if (!folders) {
collectSchemaSettings(globalSettings);
}
collectSchemaSettings(globalSettings);
}
const folders = workspace.workspaceFolders;
if (folders) {
const isMultiRoot = folders.length > 1;
for (const folder of folders) {
const folderUri = folder.uri;
const schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
const folderSchemas = schemaConfigInfo!.workspaceFolderValue;
if (Array.isArray(folderSchemas)) {
collectSchemaSettings(folderSchemas, folderUri, isMultiRoot);
const schemaConfigInfo = workspace.getConfiguration('json', folder.uri).inspect<JSONSchemaSettings[]>('schemas');
if (schemaConfigInfo && Array.isArray(schemaConfigInfo.workspaceFolderValue)) {
collectSchemaSettings(schemaConfigInfo.workspaceFolderValue, folder.uri);
}
if (Array.isArray(globalSettings)) {
collectSchemaSettings(globalSettings, folderUri, isMultiRoot);
}
}
}
return settings;
@ -572,7 +524,7 @@ function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri): string | unde
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
}
} else if (folderUri && (url[0] === '.' || url[0] === '/')) {
url = Uri.joinPath(folderUri, url).toString();
url = Uri.joinPath(folderUri, url).toString(false);
}
return url;
}

View file

@ -67,7 +67,8 @@ The server supports the following settings:
- `schemas`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content.
- `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard. Exclusion patterns can also be defined and start with '!'. A file matches when there is at least one matching pattern and the last matching pattern is not an exclusion pattern.
- `url`: The URL of the schema, optional when also a schema is provided.
- `schema`: The schema content.
- `schema`: The schema content, optional
- `folderUri`: If provided, the association is only used if the document is located in the given folder (directly or indirectly)
- `resultLimit`: The max number of color decorators and outline symbols to be computed (for performance reasons)
- `jsonFoldingLimit`: The max number of folding ranges to be computed for json documents (for performance reasons)
- `jsoncFoldingLimit`: The max number of folding ranges to be computed for jsonc documents (for performance reasons)
@ -170,6 +171,10 @@ interface ISchemaAssociation {
* A match succeeds when there is at least one pattern matching and last matching pattern does not start with '!'.
*/
fileMatch: string[];
/**
* If provided, the association is only used if the validated document is located in the given folder (directly or indirectly)
*/
folderUri?: string;
/*
* The schema for the given URI.
* If no schema is provided, the schema will be fetched with the schema request service (if available).

View file

@ -12,12 +12,12 @@
},
"main": "./out/node/jsonServerMain",
"dependencies": {
"@vscode/l10n": "^0.0.11",
"jsonc-parser": "^3.2.0",
"request-light": "^0.7.0",
"vscode-json-languageservice": "^5.1.4",
"vscode-json-languageservice": "^5.2.0",
"vscode-languageserver": "^8.1.0-next.6",
"vscode-uri": "^3.0.7",
"@vscode/l10n": "^0.0.11"
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"@types/mocha": "^9.1.1",

View file

@ -201,6 +201,7 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
fileMatch?: string[];
url?: string;
schema?: JSONSchema;
folderUri?: string;
}
@ -313,7 +314,7 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
uri = schema.schema.id || `vscode://schemas/custom/${index}`;
}
if (uri) {
languageSettings.schemas.push({ uri, fileMatch: schema.fileMatch, schema: schema.schema });
languageSettings.schemas.push({ uri, fileMatch: schema.fileMatch, schema: schema.schema, folderUri: schema.folderUri });
}
});
}

View file

@ -27,10 +27,10 @@ request-light@^0.7.0:
resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.7.0.tgz#885628bb2f8040c26401ebf258ec51c4ae98ac2a"
integrity sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==
vscode-json-languageservice@^5.1.4:
version "5.1.4"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-5.1.4.tgz#cbdb447f281dcd107705e7fe8fbfc0b71db7610d"
integrity sha512-ROZ1ezYQUbq9b/07xYpHtZSyyhoUk3oTTGVAEr6bU1DKr8ELaz9fsDoHno34tKtHj/Tf3deQqfjQNGKdbRuvTw==
vscode-json-languageservice@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-5.2.0.tgz#884b7f108be4310e3332167c3ea60ab17f03418c"
integrity sha512-q8Rdhu2HEddRxvlhVqwh0cWmKK+OtyMB2xRhtqXEQ7cjb0iZ14madb90iJe9fCHPjoj9CGBrq6QzuOp8OE6XWg==
dependencies:
"@vscode/l10n" "^0.0.11"
jsonc-parser "^3.2.0"