Skip to content

Commit 27aaa79

Browse files
committed
Don't use rootPath in built-in extension. For microsoft#90562
1 parent 595f984 commit 27aaa79

1 file changed

Lines changed: 73 additions & 56 deletions

File tree

  • extensions/json-language-features/client/src

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

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -76,29 +76,29 @@ let telemetryReporter: TelemetryReporter | undefined;
7676

7777
export function activate(context: ExtensionContext) {
7878

79-
let toDispose = context.subscriptions;
79+
const toDispose = context.subscriptions;
8080

8181
let rangeFormatting: Disposable | undefined = undefined;
8282

83-
let packageInfo = getPackageInfo(context);
83+
const packageInfo = getPackageInfo(context);
8484
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
8585

86-
let serverMain = readJSONFile(context.asAbsolutePath('./server/package.json')).main;
87-
let serverModule = context.asAbsolutePath(path.join('server', serverMain));
86+
const serverMain = readJSONFile(context.asAbsolutePath('./server/package.json')).main;
87+
const serverModule = context.asAbsolutePath(path.join('server', serverMain));
8888

8989
// The debug options for the server
90-
let debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
90+
const debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
9191

9292
// If the extension is launch in debug mode the debug server options are use
9393
// Otherwise the run options are used
94-
let serverOptions: ServerOptions = {
94+
const serverOptions: ServerOptions = {
9595
run: { module: serverModule, transport: TransportKind.ipc },
9696
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
9797
};
9898

99-
let documentSelector = ['json', 'jsonc'];
99+
const documentSelector = ['json', 'jsonc'];
100100

101-
let schemaResolutionErrorStatusBarItem = window.createStatusBarItem({
101+
const schemaResolutionErrorStatusBarItem = window.createStatusBarItem({
102102
id: 'status.json.resolveError',
103103
name: localize('json.resolveError', "JSON: Schema Resolution Error"),
104104
alignment: StatusBarAlignment.Right,
@@ -109,10 +109,10 @@ export function activate(context: ExtensionContext) {
109109
schemaResolutionErrorStatusBarItem.text = '$(alert)';
110110
toDispose.push(schemaResolutionErrorStatusBarItem);
111111

112-
let fileSchemaErrors = new Map<string, string>();
112+
const fileSchemaErrors = new Map<string, string>();
113113

114114
// Options to control the language client
115-
let clientOptions: LanguageClientOptions = {
115+
const clientOptions: LanguageClientOptions = {
116116
// Register the server for json documents
117117
documentSelector,
118118
initializationOptions: {
@@ -172,17 +172,17 @@ export function activate(context: ExtensionContext) {
172172
};
173173

174174
// Create the language client and start the client.
175-
let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
175+
const client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
176176
client.registerProposedFeatures();
177177

178-
let disposable = client.start();
178+
const disposable = client.start();
179179
toDispose.push(disposable);
180180
client.onReady().then(() => {
181181
const schemaDocuments: { [uri: string]: boolean } = {};
182182

183183
// handle content request
184184
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
185-
let uri = Uri.parse(uriPath);
185+
const uri = Uri.parse(uriPath);
186186
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
187187
return workspace.openTextDocument(uri).then(doc => {
188188
schemaDocuments[uri.toString()] = true;
@@ -212,15 +212,15 @@ export function activate(context: ExtensionContext) {
212212
}
213213
});
214214

215-
let handleContentChange = (uriString: string) => {
215+
const handleContentChange = (uriString: string) => {
216216
if (schemaDocuments[uriString]) {
217217
client.sendNotification(SchemaContentChangeNotification.type, uriString);
218218
return true;
219219
}
220220
return false;
221221
};
222222

223-
let handleActiveEditorChange = (activeEditor?: TextEditor) => {
223+
const handleActiveEditorChange = (activeEditor?: TextEditor) => {
224224
if (!activeEditor) {
225225
return;
226226
}
@@ -244,7 +244,7 @@ export function activate(context: ExtensionContext) {
244244
}));
245245
toDispose.push(window.onDidChangeActiveTextEditor(handleActiveEditorChange));
246246

247-
let handleRetryResolveSchemaCommand = () => {
247+
const handleRetryResolveSchemaCommand = () => {
248248
if (window.activeTextEditor) {
249249
schemaResolutionErrorStatusBarItem.text = '$(watch)';
250250
const activeDocUri = window.activeTextEditor.document.uri.toString();
@@ -282,7 +282,7 @@ export function activate(context: ExtensionContext) {
282282

283283
});
284284

285-
let languageConfiguration: LanguageConfiguration = {
285+
const languageConfiguration: LanguageConfiguration = {
286286
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
287287
indentationRules: {
288288
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
@@ -300,7 +300,7 @@ export function activate(context: ExtensionContext) {
300300
} else if (formatEnabled && !rangeFormatting) {
301301
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
302302
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
303-
let params: DocumentRangeFormattingParams = {
303+
const params: DocumentRangeFormattingParams = {
304304
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
305305
range: client.code2ProtocolConverter.asRange(range),
306306
options: client.code2ProtocolConverter.asFormattingOptions(options)
@@ -325,11 +325,11 @@ export function deactivate(): Promise<any> {
325325
}
326326

327327
function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
328-
let associations: ISchemaAssociations = {};
328+
const associations: ISchemaAssociations = {};
329329
extensions.all.forEach(extension => {
330-
let packageJSON = extension.packageJSON;
330+
const packageJSON = extension.packageJSON;
331331
if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation) {
332-
let jsonValidation = packageJSON.contributes.jsonValidation;
332+
const jsonValidation = packageJSON.contributes.jsonValidation;
333333
if (Array.isArray(jsonValidation)) {
334334
jsonValidation.forEach(jv => {
335335
let { fileMatch, url } = jv;
@@ -359,11 +359,11 @@ function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
359359
}
360360

361361
function getSettings(): Settings {
362-
let httpSettings = workspace.getConfiguration('http');
362+
const httpSettings = workspace.getConfiguration('http');
363363

364-
let resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
364+
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
365365

366-
let settings: Settings = {
366+
const settings: Settings = {
367367
http: {
368368
proxy: httpSettings.get('proxy'),
369369
proxyStrictSSL: httpSettings.get('proxyStrictSSL')
@@ -373,10 +373,18 @@ function getSettings(): Settings {
373373
resultLimit
374374
}
375375
};
376-
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
377-
let collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], rootPath?: string, fileMatchPrefix?: string) => {
378-
for (let setting of schemaSettings) {
379-
let url = getSchemaId(setting, rootPath);
376+
const schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
377+
const collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], folderUri?: Uri, isMultiRoot?: boolean) => {
378+
379+
let fileMatchPrefix = undefined;
380+
if (folderUri && isMultiRoot) {
381+
fileMatchPrefix = folderUri.toString();
382+
if (fileMatchPrefix[fileMatchPrefix.length - 1] === '/') {
383+
fileMatchPrefix = fileMatchPrefix.substr(0, fileMatchPrefix.length - 1);
384+
}
385+
}
386+
for (const setting of schemaSettings) {
387+
const url = getSchemaId(setting, folderUri);
380388
if (!url) {
381389
continue;
382390
}
@@ -385,69 +393,78 @@ function getSettings(): Settings {
385393
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
386394
settings.json!.schemas!.push(schemaSetting);
387395
}
388-
let fileMatches = setting.fileMatch;
389-
let resultingFileMatches = schemaSetting.fileMatch!;
396+
const fileMatches = setting.fileMatch;
390397
if (Array.isArray(fileMatches)) {
391-
if (fileMatchPrefix) {
392-
for (let fileMatch of fileMatches) {
398+
const resultingFileMatches = schemaSetting.fileMatch || [];
399+
schemaSetting.fileMatch = resultingFileMatches;
400+
const addMatch = (pattern: string) => { // filter duplicates
401+
if (resultingFileMatches.indexOf(pattern) === -1) {
402+
resultingFileMatches.push(pattern);
403+
}
404+
};
405+
for (const fileMatch of fileMatches) {
406+
if (fileMatchPrefix) {
393407
if (fileMatch[0] === '/') {
394-
resultingFileMatches.push(fileMatchPrefix + fileMatch);
395-
resultingFileMatches.push(fileMatchPrefix + '/*' + fileMatch);
408+
addMatch(fileMatchPrefix + fileMatch);
409+
addMatch(fileMatchPrefix + '/*' + fileMatch);
396410
} else {
397-
resultingFileMatches.push(fileMatchPrefix + '/' + fileMatch);
398-
resultingFileMatches.push(fileMatchPrefix + '/*/' + fileMatch);
411+
addMatch(fileMatchPrefix + '/' + fileMatch);
412+
addMatch(fileMatchPrefix + '/*/' + fileMatch);
399413
}
414+
} else {
415+
addMatch(fileMatch);
400416
}
401-
} else {
402-
resultingFileMatches.push(...fileMatches);
403417
}
404-
405418
}
406-
if (setting.schema) {
419+
if (setting.schema && !schemaSetting.schema) {
407420
schemaSetting.schema = setting.schema;
408421
}
409422
}
410423
};
411424

425+
const folders = workspace.workspaceFolders;
426+
412427
// merge global and folder settings. Qualify all file matches with the folder path.
413-
let globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
428+
const globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
414429
if (Array.isArray(globalSettings)) {
415-
collectSchemaSettings(globalSettings, workspace.rootPath);
430+
if (!folders) {
431+
collectSchemaSettings(globalSettings);
432+
}
416433
}
417-
let folders = workspace.workspaceFolders;
418434
if (folders) {
419-
for (let folder of folders) {
420-
let folderUri = folder.uri;
435+
const isMultiRoot = folders.length > 1;
436+
for (const folder of folders) {
437+
const folderUri = folder.uri;
421438

422-
let schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
439+
const schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
423440

424-
let folderSchemas = schemaConfigInfo!.workspaceFolderValue;
441+
const folderSchemas = schemaConfigInfo!.workspaceFolderValue;
425442
if (Array.isArray(folderSchemas)) {
426-
let folderPath = folderUri.toString();
427-
if (folderPath[folderPath.length - 1] === '/') {
428-
folderPath = folderPath.substr(0, folderPath.length - 1);
429-
}
430-
collectSchemaSettings(folderSchemas, folderUri.fsPath, folderPath);
443+
collectSchemaSettings(folderSchemas, folderUri, isMultiRoot);
431444
}
445+
if (Array.isArray(globalSettings)) {
446+
collectSchemaSettings(globalSettings, folderUri, isMultiRoot);
447+
}
448+
432449
}
433450
}
434451
return settings;
435452
}
436453

437-
function getSchemaId(schema: JSONSchemaSettings, rootPath?: string) {
454+
function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri) {
438455
let url = schema.url;
439456
if (!url) {
440457
if (schema.schema) {
441458
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
442459
}
443-
} else if (rootPath && (url[0] === '.' || url[0] === '/')) {
444-
url = Uri.file(path.normalize(path.join(rootPath, url))).toString();
460+
} else if (folderUri && (url[0] === '.' || url[0] === '/')) {
461+
url = folderUri.with({ path: path.posix.join(folderUri.path, url) }).toString();
445462
}
446463
return url;
447464
}
448465

449466
function getPackageInfo(context: ExtensionContext): IPackageInfo | undefined {
450-
let extensionPackage = readJSONFile(context.asAbsolutePath('./package.json'));
467+
const extensionPackage = readJSONFile(context.asAbsolutePath('./package.json'));
451468
if (extensionPackage) {
452469
return {
453470
name: extensionPackage.name,

0 commit comments

Comments
 (0)