Skip to content

Commit b0a40aa

Browse files
committed
refactor: retrieval of extension data into a new ExtensionData class.
Changed: - Moved `getExtensionPackageJsonData`, `setExtensionData`, `getExtensionData` methods into a new `ExtensionData` class for simplicity and better organisation. - Simplified the `getExtensionPackageJsonData` method to get all package.json data not just a select few. By using the new type `IPackageJson`, we can properly type the data as package.json instead of a generic `object` or `any`. - Changed the `name` variable to `namespace`, simplied it's code and added it to the `contributes.configuration` object of the packageJson data, since it's the namespace of the settings - Changed the `name` variable to `namespace`, simplied it's code and added it to the `contributes.configuration` object of the packageJson data, since it's the namespace of the configuration settings. - Split `setExtensionData` into 2 methods: `setExtensionData` and `createExtensionData`; and simplified the code. - `createExtensionData` to create the extension data object, defining the keys and values for the Map. The keys as defined here will also be used for type inference for VScode intellisense in the new `get` method. - `setExtensionData` to set the data as defined in `createExtensionData` method into the `extensionData` Map. - Changed all references to the old `getExtensionData` method to use the `get` method of the new `ExtensionData` class. - Renamed the `Configuration` property `extensionDetails` to `extensionData`; and instantiate the `ExtensionData` class as it's value. Added: - Added new `get` method to get the extension's data by a specified key. VScode intellisense auto-suggests the keys by using type inference from the keys set in `createExtensionData` method. This is important so remembering or looking up the keys isn't a pain. - Added `getAll` method to get all extension data as readonly so it can only be logged in the Output Channel. - Added a new dependency `package-json-type` to allow package.json typings as `IPackageJson`.
1 parent e5063bc commit b0a40aa

File tree

4 files changed

+134
-93
lines changed

4 files changed

+134
-93
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
},
111111
"dependencies": {
112112
"is-wsl": "^3.1.0",
113-
"jsonc-parser": "^3.3.1"
113+
"jsonc-parser": "^3.3.1",
114+
"package-json-type": "^1.0.3"
114115
}
115116
}

src/configuration.ts

Lines changed: 17 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import isWsl from "is-wsl";
99
import {Rules} from "./rules";
1010
import {Logger} from "./logger";
1111
import * as utils from "./utils";
12+
import {ExtensionData} from "./extensionData";
1213

1314
export class Configuration {
1415
/**************
@@ -23,9 +24,10 @@ export class Configuration {
2324
private logger: Logger;
2425

2526
/**
26-
* This extension details in the form of a key:value Map object, for ease of use.
27+
* This extension data class instance.
28+
* @type {ExtensionData}
2729
*/
28-
private extensionDetails = new Map<string, any>();
30+
private extensionData: ExtensionData = new ExtensionData();
2931

3032
/**
3133
* A key:value Map object of language IDs and their config file paths.
@@ -66,10 +68,8 @@ export class Configuration {
6668
public constructor(logger: Logger) {
6769
this.logger = logger;
6870

69-
this.setExtensionData();
70-
7171
// Always output extension information to channel on activate.
72-
this.logger.debug(`Extension details:`, this.extensionDetails);
72+
this.logger.debug(`Extension details:`, this.extensionData.getAll());
7373

7474
this.findAllLanguageConfigFilePaths();
7575
this.setLanguageConfigDefinitions();
@@ -198,86 +198,13 @@ export class Configuration {
198198
}
199199
}
200200

201-
/**
202-
* Get the names, id, and version of this extension from package.json.
203-
*
204-
* @returns {object} An object containing the extension id, name, display name, and version.
205-
*/
206-
private getExtensionPackageJsonData(): {id: string; name: string; displayName: string; version: string} {
207-
const packageJSON = utils.readJsonFile(__dirname + "/../../package.json");
208-
209-
const displayName: string = packageJSON.displayName;
210-
const fullname: string = packageJSON.name;
211-
const id: string = `${packageJSON.publisher}.${fullname}`;
212-
const version: string = packageJSON.version;
213-
214-
let nameParts = fullname.split("-");
215-
nameParts[0] = "auto";
216-
const name = nameParts.join("-");
217-
218-
return {id: id, name: name, displayName: displayName, version: version};
219-
}
220-
221-
/**
222-
* Set the extension data into the extensionDetails Map.
223-
*/
224-
private setExtensionData() {
225-
const extensionPackageJsonData = this.getExtensionPackageJsonData();
226-
227-
const id = extensionPackageJsonData.id;
228-
const name = extensionPackageJsonData.name;
229-
const displayName = extensionPackageJsonData.displayName;
230-
const version = extensionPackageJsonData.version;
231-
232-
// The path to the user extensions.
233-
const userExtensionsPath = isWsl
234-
? path.join(vscode.env.appRoot, "../../", "extensions")
235-
: path.join(vscode.extensions.getExtension(id).extensionPath, "../");
236-
237-
// The path to the built-in extensions.
238-
// This env variable changes when on WSL to it's WSL-built-in extensions path.
239-
const builtInExtensionsPath = path.join(vscode.env.appRoot, "extensions");
240-
241-
this.extensionDetails.set("id", id);
242-
this.extensionDetails.set("name", name);
243-
this.extensionDetails.set("displayName", displayName);
244-
this.extensionDetails.set("version", version);
245-
this.extensionDetails.set("userExtensionsPath", userExtensionsPath);
246-
this.extensionDetails.set("builtInExtensionsPath", builtInExtensionsPath);
247-
248-
if (isWsl) {
249-
// Get the root path to VS Code from the env variable, and use it to get
250-
// the Windows built-in extensions.
251-
const windowsBuiltInExtensionsPathFromWsl = path.join(process.env.VSCODE_CWD, "resources/app/extensions");
252-
253-
// Get the Windows user extensions path from env variable.
254-
const windowsUserExtensionsPathFromWsl = path.dirname(process.env.VSCODE_WSL_EXT_LOCATION);
255-
256-
this.extensionDetails.set("WindowsUserExtensionsPathFromWsl", windowsUserExtensionsPathFromWsl);
257-
this.extensionDetails.set("WindowsBuiltInExtensionsPathFromWsl", windowsBuiltInExtensionsPathFromWsl);
258-
}
259-
}
260-
261-
/**
262-
* Get the extension's details.
263-
*
264-
* @param {string} key The key of the specific extension detail to get.
265-
*
266-
* @returns {any} Returns a value of a specific key.
267-
*/
268-
public getExtensionData(key: string): any {
269-
if (this.extensionDetails.has(key)) {
270-
return this.extensionDetails.get(key);
271-
}
272-
}
273-
274201
/**
275202
* Get all the extension's configuration settings.
276203
*
277204
* @returns {vscode.WorkspaceConfiguration}
278205
*/
279206
public getConfiguration(): vscode.WorkspaceConfiguration {
280-
return vscode.workspace.getConfiguration(this.getExtensionData("name"), null);
207+
return vscode.workspace.getConfiguration(this.extensionData.get("name"), null);
281208
}
282209

283210
/**
@@ -368,15 +295,15 @@ export class Configuration {
368295
// If running in WSL...
369296
if (isWsl) {
370297
// Get the Windows user and built-in extensions paths.
371-
const windowsUserExtensionsPath = this.getExtensionData("WindowsUserExtensionsPathFromWsl");
372-
const windowsBuiltInExtensionsPath = this.getExtensionData("WindowsBuiltInExtensionsPathFromWsl");
298+
const windowsUserExtensionsPath = this.extensionData.get("WindowsUserExtensionsPathFromWsl");
299+
const windowsBuiltInExtensionsPath = this.extensionData.get("WindowsBuiltInExtensionsPathFromWsl");
373300

374301
// Read the paths and create arrays of the extensions.
375-
const builtInExtensions = this.readExtensionsFromDirectory(windowsBuiltInExtensionsPath);
376-
const userExtensions = this.readExtensionsFromDirectory(windowsUserExtensionsPath);
302+
const windowsBuiltInExtensions = this.readExtensionsFromDirectory(windowsBuiltInExtensionsPath);
303+
const windowsUserExtensions = this.readExtensionsFromDirectory(windowsUserExtensionsPath);
377304

378305
// Combine the built-in and user extensions into the extensions array.
379-
extensions.push(...builtInExtensions, ...userExtensions);
306+
extensions.push(...windowsBuiltInExtensions, ...windowsUserExtensions);
380307
}
381308

382309
// Add all installed extensions (including built-in ones) into the extensions array.
@@ -916,7 +843,7 @@ export class Configuration {
916843
*/
917844
private handleChangeBladeMultiLineBlock(textEditor: vscode.TextEditor) {
918845
let langId = textEditor.document.languageId;
919-
const extensionName = this.getExtensionData("name");
846+
const extensionName = this.extensionData.get("name");
920847

921848
// Only carry out function if languageId is blade.
922849
if (langId === "blade" && !this.isLangIdDisabled(langId)) {
@@ -955,25 +882,25 @@ export class Configuration {
955882
private logDebugInfo() {
956883
// The path to the built-in extensions. The env variable changes when on WSL.
957884
// So we can use it for both Windows and WSL.
958-
const builtInExtensionsPath = this.getExtensionData("builtInExtensionsPath");
885+
const builtInExtensionsPath = this.extensionData.get("builtInExtensionsPath");
959886

960887
let extensionsPaths = {};
961888

962889
if (isWsl) {
963890
// Get the Windows user and built-in extensions paths.
964-
const windowsUserExtensionsPath = this.getExtensionData("WindowsUserExtensionsPathFromWsl");
965-
const windowsBuiltInExtensionsPath = this.getExtensionData("WindowsBuiltInExtensionsPathFromWsl");
891+
const windowsUserExtensionsPath = this.extensionData.get("WindowsUserExtensionsPathFromWsl");
892+
const windowsBuiltInExtensionsPath = this.extensionData.get("WindowsBuiltInExtensionsPathFromWsl");
966893

967894
extensionsPaths = {
968895
"Windows-installed Built-in Extensions Path": windowsBuiltInExtensionsPath,
969896
"Windows-installed User Extensions Path": windowsUserExtensionsPath,
970897
"WSL-installed Built-in Extensions Path": builtInExtensionsPath,
971-
"WSL-installed User Extensions Path": this.getExtensionData("userExtensionsPath"),
898+
"WSL-installed User Extensions Path": this.extensionData.get("userExtensionsPath"),
972899
};
973900
} else {
974901
extensionsPaths = {
975902
"Built-in Extensions Path": builtInExtensionsPath,
976-
"User Extensions Path": this.getExtensionData("userExtensionsPath"),
903+
"User Extensions Path": this.extensionData.get("userExtensionsPath"),
977904
};
978905
}
979906

src/extension.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import * as vscode from "vscode";
44

55
import {Configuration} from "./configuration";
66
import {Logger} from "./logger";
7+
import {ExtensionData} from "./extensionData";
78

89
const logger = new Logger();
10+
const extensionData = new ExtensionData();
911
logger.setupOutputChannel();
1012
let configuration = new Configuration(logger);
1113

@@ -17,8 +19,9 @@ export function activate(context: vscode.ExtensionContext) {
1719

1820
disposables.push(...configureCommentBlocksDisposable, ...registerCommandsDisposable);
1921

20-
const extensionName = configuration.getExtensionData("name");
21-
const extensionDisplayName = configuration.getExtensionData("displayName");
22+
const extensionName = extensionData.get("name");
23+
24+
const extensionDisplayName = extensionData.get("displayName");
2225

2326
let disabledLangConfig: string[] = configuration.getConfigurationValue<string[]>("disabledLanguages");
2427

src/extensionData.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import * as vscode from "vscode";
2+
import * as path from "path";
3+
import isWsl from "is-wsl";
4+
import {IPackageJson} from "package-json-type";
5+
6+
import {readJsonFile} from "./utils";
7+
8+
export class ExtensionData {
9+
/**
10+
* This extension details in the form of a key:value Map object.
11+
*
12+
* @type {Map<string, string>}
13+
*/
14+
private extensionData = new Map<string, string>();
15+
16+
/**
17+
* The package.json data for this extension.
18+
*
19+
* @type {IPackageJson}
20+
*/
21+
private packageJsonData: IPackageJson;
22+
23+
public constructor() {
24+
this.packageJsonData = this.getExtensionPackageJsonData();
25+
this.setExtensionData();
26+
}
27+
28+
/**
29+
* Get the names, id, and version of this extension from package.json.
30+
*
31+
* @returns {IPackageJson} The package.json data for this extension, plus the new `id`, and `contributes.configuration.namespace` keys.
32+
*/
33+
private getExtensionPackageJsonData(): IPackageJson {
34+
const packageJSON: IPackageJson = readJsonFile(__dirname + "/../../package.json");
35+
36+
// Set the id (publisher.name) into the packageJSON object as a new `id` key.
37+
packageJSON.id = `${packageJSON.publisher}.${packageJSON.name}`;
38+
39+
// The configuration settings namespace is a shortened version of the extension name.
40+
// We just need to replace "automatic" with "auto" in the name.
41+
const settingsNamespace: string = packageJSON.name.replace("automatic", "auto");
42+
// Set the namespace to the packageJSON `configuration` object as a new `namespace` key.
43+
packageJSON.contributes.configuration.namespace = settingsNamespace;
44+
45+
return packageJSON;
46+
}
47+
48+
/**
49+
* Set the extension data into the extensionData Map.
50+
*/
51+
private setExtensionData() {
52+
// Set all entries in the extensionData Map.
53+
Object.entries(this.createExtensionData()).forEach(([key, value]) => {
54+
this.extensionData.set(key, value);
55+
});
56+
}
57+
58+
/**
59+
* Create the extension data object for the extensionData Map.
60+
* It also helps for type inference intellisense in the get method.
61+
*
62+
* @returns The extension data object with keys and values.
63+
*/
64+
private createExtensionData() {
65+
// The path to the user extensions.
66+
const userExtensionsPath = isWsl
67+
? path.join(vscode.env.appRoot, "../../", "extensions")
68+
: path.join(vscode.extensions.getExtension(id).extensionPath, "../");
69+
70+
71+
// Set the keys and values for the Map.
72+
// The keys will also be used for type inference in VSCode intellisense.
73+
return {
74+
id: this.packageJsonData.id,
75+
name: this.packageJsonData.contributes.configuration.namespace,
76+
displayName: this.packageJsonData.displayName,
77+
version: this.packageJsonData.version,
78+
userExtensionsPath: userExtensionsPath,
79+
// The path to the built-in extensions.
80+
// This env variable changes when on WSL to it's WSL-built-in extensions path.
81+
builtInExtensionsPath: path.join(vscode.env.appRoot, "extensions"),
82+
83+
// Only set these if running in WSL.
84+
...(isWsl && {
85+
WindowsUserExtensionsPathFromWsl: path.dirname(process.env.VSCODE_WSL_EXT_LOCATION!),
86+
WindowsBuiltInExtensionsPathFromWsl: path.join(process.env.VSCODE_CWD!, "resources/app/extensions"),
87+
}),
88+
} as const;
89+
}
90+
91+
/**
92+
* Get the extension's data by a specified key.
93+
*
94+
* @param {K} key The key of the extension detail to get.
95+
*
96+
* @returns {ReturnType<typeof this.createExtensionData>[K] | undefined} The value of the extension detail, or undefined if the key does not exist.
97+
*/
98+
public get<K extends keyof ReturnType<typeof this.createExtensionData>>(key: K): ReturnType<typeof this.createExtensionData>[K] | undefined {
99+
return this.extensionData.get(key) as ReturnType<typeof this.createExtensionData>[K] | undefined;
100+
}
101+
102+
/**
103+
* Get all extension data.
104+
*
105+
* @returns {ReadonlyMap<string, string>} A read-only Map containing all extension details.
106+
*/
107+
public getAll(): ReadonlyMap<string, string> {
108+
return this.extensionData;
109+
}
110+
}

0 commit comments

Comments
 (0)