1// Copyright 2023 The Pigweed Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may not 4// use this file except in compliance with the License. You may obtain a copy of 5// the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12// License for the specific language governing permissions and limitations under 13// the License. 14 15import * as hjson from 'hjson'; 16import * as vscode from 'vscode'; 17 18/** 19 * Schema for extensions.json 20 */ 21export interface ExtensionsJson { 22 recommendations?: string[]; 23 unwantedRecommendations?: string[]; 24} 25 26/** 27 * Partial schema for the workspace config file 28 */ 29interface WorkspaceConfig { 30 extensions?: ExtensionsJson; 31} 32 33// When the project is opened directly (i.e., by opening the repo directory), 34// we have direct access to extensions.json. But if the project is part of a 35// workspace (https://code.visualstudio.com/docs/editor/workspaces), we'll get 36// a combined config that includes the equivalent of extensions.json associated 37// with the "extensions" key. This is taken into consideration only for the sake 38// of completeness; Pigweed doesn't currently support the use of workspaces. 39type LoadableConfig = ExtensionsJson & WorkspaceConfig; 40 41/** 42 * Load a config file that contains extensions.json data. This could be 43 * extensions.json itself, or a workspace file that contains the equivalent. 44 * @param uri - A file path to load 45 * @returns - The extensions.json file data 46 */ 47export async function loadExtensionsJson( 48 uri: vscode.Uri, 49): Promise<ExtensionsJson> { 50 const buffer = await vscode.workspace.fs.readFile(uri); 51 const config: LoadableConfig = hjson.parse(buffer.toString()); 52 53 if (config.extensions) { 54 return config.extensions; 55 } 56 57 return config as ExtensionsJson; 58} 59 60/** 61 * Find and return the extensions.json data for the project. 62 * @param includeWorkspace - Also search workspace files 63 * @returns The extensions.json file data 64 */ 65export async function getExtensionsJson( 66 includeWorkspace = false, 67): Promise<ExtensionsJson | null> { 68 const files = await vscode.workspace.findFiles( 69 '.vscode/extensions.json', 70 '**/node_modules/**', 71 ); 72 73 if (includeWorkspace) { 74 const workspaceFile = vscode.workspace.workspaceFile; 75 76 if (workspaceFile) { 77 files.push(workspaceFile); 78 } 79 } 80 81 if (files.length == 0) { 82 return null; 83 } else { 84 if (files.length > 1) { 85 vscode.window.showWarningMessage( 86 'Found multiple extensions.json! Will only use the first.', 87 ); 88 } 89 90 return await loadExtensionsJson(files[0]); 91 } 92} 93