From 83bb5351115de4a9f819c84f736220a5a9002120 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 3 Jul 2025 04:29:08 +0100 Subject: [PATCH 01/14] refactor: extract debug logging from `constructor` into new method - Added the new `logDebugInfo` method to log all debugging information to the Output channel. - Extracted all the debug logging from the `constructor` into it's own method to keep the constructor clean. - Changed the format of the data logged for the supported languages. Instead of logging the `Map`s, we now utilise the auto-generated language definitions files. This is because the single-line languages are reformatted in a human-readable way to output to the file, so it would be better reading this formatted file than the JS `Map`. --- src/configuration.ts | 47 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 8c643e1..b573964 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -65,21 +65,6 @@ export class Configuration { const extensionVersion = vscode.extensions.getExtension(extensionId)?.packageJSON.version; this.logger.info(`Extension: ${extensionId} (${extensionVersion})`); - const env = { - "OS": process.platform, - "Platform": process.platform, - "VS Code Version": vscode.version, - "VS Code Root Path": vscode.env.appRoot, - "VS Code Built-in Extensions Path": `${vscode.env.appRoot}\\extensions`, - "VS Code Host": vscode.env.appHost, - "VS Code Remote Name": vscode.env.remoteName || "local", - "Other System Env Variables": process.env, - }; - this.logger.debug("Environment:", env); - - // Log the extension's user configuration settings. - this.logger.debug("Configuration settings:", this.getConfiguration()); - this.findAllLanguageConfigFilePaths(); this.setLanguageConfigDefinitions(); @@ -87,11 +72,7 @@ export class Configuration { this.setSingleLineCommentLanguageDefinitions(); this.writeCommentLanguageDefinitionsToJsonFile(); - // Log the objects for debugging purposes. - this.logger.debug("The language config filepaths found are:", this.languageConfigFilePaths); - this.logger.debug("The language configs found are:", this.languageConfigs); - this.logger.debug("The supported languages for multi-line blocks:", this.multiLineBlocksMap); - this.logger.debug("The supported languages single-line blocks:", this.singleLineBlocksMap); + this.logDebugInfo(); } /** @@ -993,4 +974,30 @@ export class Configuration { this.setBladeComments(false); } } + + /** + * Logs the environment, configuration settings, and language configs for debugging purposes. + */ + private logDebugInfo() { + const env = { + "OS": process.platform, + "Platform": process.platform, + "VS Code Version": vscode.version, + "VS Code Root Path": vscode.env.appRoot, + "VS Code Built-in Extensions Path": `${vscode.env.appRoot}\\extensions`, + "VS Code Host": vscode.env.appHost, + "VS Code Remote Name": vscode.env.remoteName || "local", + "Other System Env Variables": process.env, + }; + this.logger.debug("Environment:", env); + + // Log the extension's user configuration settings. + this.logger.debug("Configuration settings:", this.getConfiguration()); + + // Log the objects for debugging purposes. + this.logger.debug("The language config filepaths found are:", this.languageConfigFilePaths); + this.logger.debug("The language configs found are:", this.languageConfigs); + this.logger.debug("The supported languages for multi-line blocks:", this.readJsonFile(this.multiLineLangDefinitionFilePath)); + this.logger.debug("The supported languages for single-line blocks:", this.readJsonFile(this.singleLineLangDefinitionFilePath)); + } } From 91ed4012277c506807b6119a50d7b40db04a8e59 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 3 Jul 2025 04:29:08 +0100 Subject: [PATCH 02/14] refactor: extract debug logging from `constructor` into new method - Added the new `logDebugInfo` method to log all debugging information to the Output channel. - Extracted all the debug logging from the `constructor` into it's own method to keep the constructor clean. - Changed the format of the data logged for the supported languages. Instead of logging the `Map`s, we now utilise the auto-generated language definitions files. This is because the single-line languages are reformatted in a human-readable way to output to the file, so it would be better reading this formatted file than the JS `Map`. --- src/configuration.ts | 47 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 8c643e1..b573964 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -65,21 +65,6 @@ export class Configuration { const extensionVersion = vscode.extensions.getExtension(extensionId)?.packageJSON.version; this.logger.info(`Extension: ${extensionId} (${extensionVersion})`); - const env = { - "OS": process.platform, - "Platform": process.platform, - "VS Code Version": vscode.version, - "VS Code Root Path": vscode.env.appRoot, - "VS Code Built-in Extensions Path": `${vscode.env.appRoot}\\extensions`, - "VS Code Host": vscode.env.appHost, - "VS Code Remote Name": vscode.env.remoteName || "local", - "Other System Env Variables": process.env, - }; - this.logger.debug("Environment:", env); - - // Log the extension's user configuration settings. - this.logger.debug("Configuration settings:", this.getConfiguration()); - this.findAllLanguageConfigFilePaths(); this.setLanguageConfigDefinitions(); @@ -87,11 +72,7 @@ export class Configuration { this.setSingleLineCommentLanguageDefinitions(); this.writeCommentLanguageDefinitionsToJsonFile(); - // Log the objects for debugging purposes. - this.logger.debug("The language config filepaths found are:", this.languageConfigFilePaths); - this.logger.debug("The language configs found are:", this.languageConfigs); - this.logger.debug("The supported languages for multi-line blocks:", this.multiLineBlocksMap); - this.logger.debug("The supported languages single-line blocks:", this.singleLineBlocksMap); + this.logDebugInfo(); } /** @@ -993,4 +974,30 @@ export class Configuration { this.setBladeComments(false); } } + + /** + * Logs the environment, configuration settings, and language configs for debugging purposes. + */ + private logDebugInfo() { + const env = { + "OS": process.platform, + "Platform": process.platform, + "VS Code Version": vscode.version, + "VS Code Root Path": vscode.env.appRoot, + "VS Code Built-in Extensions Path": `${vscode.env.appRoot}\\extensions`, + "VS Code Host": vscode.env.appHost, + "VS Code Remote Name": vscode.env.remoteName || "local", + "Other System Env Variables": process.env, + }; + this.logger.debug("Environment:", env); + + // Log the extension's user configuration settings. + this.logger.debug("Configuration settings:", this.getConfiguration()); + + // Log the objects for debugging purposes. + this.logger.debug("The language config filepaths found are:", this.languageConfigFilePaths); + this.logger.debug("The language configs found are:", this.languageConfigs); + this.logger.debug("The supported languages for multi-line blocks:", this.readJsonFile(this.multiLineLangDefinitionFilePath)); + this.logger.debug("The supported languages for single-line blocks:", this.readJsonFile(this.singleLineLangDefinitionFilePath)); + } } From 446a9ba8708d1868ad63775a923ddbb5b981823e Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Wed, 9 Jul 2025 19:02:48 +0100 Subject: [PATCH 03/14] build: add new dependency to detect if WSL is being used. --- package.json | 1 + src/configuration.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/package.json b/package.json index 91922b1..25b2208 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,7 @@ "typescript": "^5.7" }, "dependencies": { + "is-wsl": "^3.1.0", "jsonc-parser": "^3.3.1" } } diff --git a/src/configuration.ts b/src/configuration.ts index b573964..7ab639e 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -5,6 +5,7 @@ import * as vscode from "vscode"; import * as fs from "node:fs"; import * as jsonc from "jsonc-parser"; import * as path from "path"; +import isWsl from "is-wsl"; import {Rules} from "./rules"; import {Logger} from "./logger"; From 7fe2f04df08feca16124a59ffd7d0f10a3932f72 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 02:01:59 +0100 Subject: [PATCH 04/14] feat: add the ability to get all Windows extensions when running on WSL. This is a work around for the fact that the `vscode.extensions.all` API can't find any built-in extensions on the Windows-side when running in WSL. It only gets the WSL-installed extensions, which caused the extension not to work in yCodeTech/auto-comment-blocks#6 There is an open issue and a proposed API change in the sourcecode since 2022, but hasn't been released as a public API. See https://github.com/microsoft/vscode/issues/145307 for more info. Added: - Added new `getExtensionsPathsFromWslEnv` method to retrieve the Windows built-in and user extensions paths from the environment variables when running in WSL. - Added new `readExtensionsFromDirectory` method to read the extensions paths and retrieve each extension data. Changed: - Changed `findAllLanguageConfigFilePaths` method to check if the extension is running in WSL. If it `isWsl`, then it calls the new `getExtensionsPathsFromWslEnv` method to get the paths, and uses the new `readExtensionsFromDirectory` to obtain the extensions data. We construct a new `extensions` array with all the windows-installed built-in and user extensions and also the WSL-installed extensions via `vscode.extensions.all`. (The extension will still work on Windows without WSL due to it using `vscode.extensions.all` outside of the `isWsl` check.) - Changed the `for...of` loop to iterate through the new `extensions` array. --- src/configuration.ts | 90 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index 7ab639e..0e6f9bc 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -304,8 +304,27 @@ export class Configuration { * (built-in and 3rd party). */ private findAllLanguageConfigFilePaths() { + const extensions: any[] = []; + + // If running in WSL... + if (isWsl) { + // Get the Windows built-in and user extensions paths from WSL environment variables. + const {builtInExtensionsPathFromWsl, userExtensionsPathFromWsl} = this.getExtensionsPathsFromWslEnv(); + + // Read the paths and create arrays of the extensions. + const builtInExtensions = this.readExtensionsFromDirectory(builtInExtensionsPathFromWsl); + const userExtensions = this.readExtensionsFromDirectory(userExtensionsPathFromWsl); + + // Combine the built-in and user extensions into the extensions array. + extensions.push(...builtInExtensions, ...userExtensions); + } + + // Add all installed extensions (including built-in ones) into the extensions array. + // If running WSL, these will be the WSL-installed extensions. + extensions.push(...vscode.extensions.all); + // Loop through all installed extensions, including built-in extensions - for (let extension of vscode.extensions.all) { + for (let extension of extensions) { const packageJSON = extension.packageJSON; // If an extension package.json has "contributes" key, @@ -425,6 +444,41 @@ export class Configuration { fs.writeFileSync(filepath, JSON.stringify(data, null, "\t")); } + /** + * Read the directory in the given path and return an array of objects with the data of + * all extensions found in the directory. + * + * @param {string} extensionsPath The path where extensions are stored. + * + * @returns {Array<{ id: string; extensionPath: string; packageJSON: any }>} + */ + private readExtensionsFromDirectory(extensionsPath: string): Array<{id: string; extensionPath: string; packageJSON: any}> { + // Create an array to hold the found extensions. + const foundExtensions: Array<{id: string; extensionPath: string; packageJSON: any}> = []; + + fs.readdirSync(extensionsPath).forEach((extensionName) => { + const extensionPath = path.join(extensionsPath, extensionName); + + // If the extensionName is a directory... + if (fs.statSync(extensionPath).isDirectory()) { + // Get the package.json file path. + const packageJSONPath = path.join(extensionPath, "package.json"); + + // If the package.json file exists... + if (fs.existsSync(packageJSONPath)) { + const packageJSON = this.readJsonFile(packageJSONPath); + + const id = `${packageJSON.publisher}.${packageJSON.name}`; + + // Push the extension data object into the array. + foundExtensions.push({id, extensionPath, packageJSON}); + } + } + }); + + return foundExtensions; + } + /** * Get the multi-line languages from the Map. * @@ -976,6 +1030,40 @@ export class Configuration { } } + /** + * Gets the user and built-in extensions paths on Windows from WSL environment variables. + * + * @returns {Object} An object containing the user and built-in extensions paths. + */ + private getExtensionsPathsFromWslEnv() { + const extensionNames = this.getExtensionNames(); + + /** Built-in Extensions */ + + // Get the path to the VS Code's exectutable from the VSCODE_CWD environment variable. + // The variable will be a path like: + // "/mnt/c/Users/USERNAME/AppData/Local/Programs/Microsoft VS Code". + const vscodePathFromWsl = process.env.VSCODE_CWD; + // Append "resources/app/extensions" to the base path to form the path to the + // built-in extensions. + const builtInExtensionsPathFromWsl = path.join(vscodePathFromWsl, "resources/app/extensions"); + + /** User Extensions */ + + // Get the user extensions path from VSCODE_WSL_EXT_LOCATION env variable. + // If it's not set, then use an empty string. + // The variable will be a path like: + // "/mnt/c/Users/USERNAME/.vscode/extensions/ms-vscode-remote.remote-wsl-0.99.0". + // So we just need to return the directory name like: + // "/mnt/c/Users/USERNAME/.vscode/extensions/" + const userExtensionsPathFromWsl = path.dirname(process.env.VSCODE_WSL_EXT_LOCATION); + + return { + builtInExtensionsPathFromWsl, + userExtensionsPathFromWsl, + }; + } + /** * Logs the environment, configuration settings, and language configs for debugging purposes. */ From 21bdd89f2233340be9a6dff42a1a2e1c55b0c0b1 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 02:10:45 +0100 Subject: [PATCH 05/14] refactor: `logDebugInfo` method to log different stuff when on WSL. Added: - Added an `isWsl` check, and uses the new `getExtensionsPathsFromWslEnv` method to log the Windows extensions paths from WSL. Changed: - Refactored all "VS Code" items into a new object so that we're not repeating "VS Code" multiple times. This makes for a better reading experience. --- src/configuration.ts | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 0e6f9bc..5e4b1ec 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1068,14 +1068,38 @@ export class Configuration { * Logs the environment, configuration settings, and language configs for debugging purposes. */ private logDebugInfo() { + // The path to the built-in extensions. The env variable changes when on WSL. + // So we can use it for both Windows and WSL. + const builtInExtensionsPath = path.join(vscode.env.appRoot, "extensions"); + + let extensionsPaths = {}; + + if (isWsl) { + // Get the Windows user and built-in extensions paths on Windows from WSL environment variables. + const {builtInExtensionsPathFromWsl, userExtensionsPathFromWsl} = this.getExtensionsPathsFromWslEnv(); + + extensionsPaths = { + "Windows-installed Built-in Extensions Path": builtInExtensionsPathFromWsl, + "Windows-installed User Extensions Path": userExtensionsPathFromWsl, + "WSL-installed Built-in Extensions Path": builtInExtensionsPath, + "WSL-installed User Extensions Path": path.join(vscode.env.appRoot, "../../", "extensions"), + }; + } else { + extensionsPaths = { + "Built-in Extensions Path": builtInExtensionsPath, + "User Extensions Path": path.join(process.env.USERPROFILE, ".vscode", "extensions"), + }; + } + const env = { "OS": process.platform, "Platform": process.platform, - "VS Code Version": vscode.version, - "VS Code Root Path": vscode.env.appRoot, - "VS Code Built-in Extensions Path": `${vscode.env.appRoot}\\extensions`, - "VS Code Host": vscode.env.appHost, - "VS Code Remote Name": vscode.env.remoteName || "local", + "VS Code Details": { + "Version": vscode.version, + "Remote Name": vscode.env.remoteName || "local", + "Host": vscode.env.appHost, + ...extensionsPaths, + }, "Other System Env Variables": process.env, }; this.logger.debug("Environment:", env); From 5a9671556f16e746581b7edb1896f53653a78b97 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 03:01:57 +0100 Subject: [PATCH 06/14] fix: keybindings, docs, and paths to enable usage on macOS. --- README.md | 6 +++--- package.json | 5 +++-- src/configuration.ts | 5 ++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 03e0a91..656cf7f 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ Use `/*!` in all file types that support the normal `/*` comments to start a QDo #### Normal comment blocks -Using the normal comment block `/* */` either typing manually or the native VScode command "Toggle Block Comment" (`editor.action.blockComment`, native keybinding `shift + alt + a`), the block will have the same on enter functionality as described above. +Using the normal comment block `/* */` either typing manually or the native VScode command "Toggle Block Comment" (`editor.action.blockComment`, native keybinding shift + alt + a (macOS: shift + option + a)), the block will have the same on enter functionality as described above. ![block-comments](https://raw.githubusercontent.com/yCodeTech/auto-comment-blocks/master/img/block-comments.gif) @@ -156,9 +156,9 @@ Reload the extension after changing any settings. - `auto-comment-blocks.multiLineStyleBlocks`: Add language IDs here to enable multi-line comment blocks support for that language, allowing unsupported languages to have comment completion. The default is `['blade', 'html']`" -- `auto-comment-blocks.overrideDefaultLanguageMultiLineComments`: A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode "Toggle Block Comment" `editor.action.blockComment` command (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}` +- `auto-comment-blocks.overrideDefaultLanguageMultiLineComments`: A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode "Toggle Block Comment" `editor.action.blockComment` command (native Keybinding shift + alt + a (macOS: shift + option + a)). eg. `{'php': '/*!'}` -- `auto-comment-blocks.bladeOverrideComments`: When enabled, Blade-style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default `ctrl + shift + m`. If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used. +- `auto-comment-blocks.bladeOverrideComments`: When enabled, Blade-style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default ctrl + shift + m (macOS: cmd + shift + m). If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used. ## Known Issues diff --git a/package.json b/package.json index 25b2208..3f1679e 100644 --- a/package.json +++ b/package.json @@ -71,13 +71,13 @@ "auto-comment-blocks.overrideDefaultLanguageMultiLineComments": { "type": "object", "default": {}, - "markdownDescription": "A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode `command editor.action.blockComment` (native Keybinding `shift + alt + a`). eg. `{'php': '/*!'}`" + "markdownDescription": "A key : value pairing of language IDs and the beginning portion of a multi-line comment style, to override the default comment style for the vscode `command editor.action.blockComment` (native Keybinding `shift + alt + a` (macOS: `shift + option + a`)). eg. `{'php': '/*!'}`" }, "auto-comment-blocks.bladeOverrideComments": { "scope": "resource", "type": "boolean", "default": false, - "markdownDescription": "When enabled, Blade style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default `ctrl + shift + m`. If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used." + "markdownDescription": "When enabled, Blade style block comments will be used in Blade contexts. Ie. `{{-- --}}` comments will be used instead of the HTML `` comments. Keybinding to enable/disable, default `ctrl + shift + m` (macOS: `cmd + shift + m`). If `blade` language ID is set in the disabledLanguages, then the HTML `` comments will be used." } } }, @@ -90,6 +90,7 @@ { "command": "auto-comment-blocks.changeBladeMultiLineBlock", "key": "ctrl+shift+m", + "mac": "cmd+shift+m", "when": "editorTextFocus" } ] diff --git a/src/configuration.ts b/src/configuration.ts index 5e4b1ec..631a5c4 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1085,9 +1085,12 @@ export class Configuration { "WSL-installed User Extensions Path": path.join(vscode.env.appRoot, "../../", "extensions"), }; } else { + // Get the user home directory from the environment variable: + // `USERPROFILE` on Windows, `HOME` on macOS/Linux. + const userHome = process.env.USERPROFILE || process.env.HOME; extensionsPaths = { "Built-in Extensions Path": builtInExtensionsPath, - "User Extensions Path": path.join(process.env.USERPROFILE, ".vscode", "extensions"), + "User Extensions Path": path.join(userHome, ".vscode", "extensions"), }; } From 25fab483e0d86d1c49917508bc863c2c03b25abf Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 05:59:34 +0100 Subject: [PATCH 07/14] refactor: create a uniform way of obtaining this extension's details. Added: - Added new `extensionDetails` private property in `Configuration` as a Map object. - Added new `setExtensionData` method to set the data into the `extensionDetails` Map. Also added its method call into the `constructor`. - Added new `getExtensionData` public method to get the value of a specified key from the `extensionDetails` Map. Changed: - Refactored `getExtensionNames` to be more generic. This will be used in the new `setExtensionData` method to get and set the names, id and version into the `extensionDetails` Map. - Changed the name to `getExtensionPackageJsonData`. - Changed it's visibility to `private`. - Changed the reading of the package.json file to use the `readJsonFile` method as it does the exact same thing, and makes it DRYer. - Added the extension's version. - Changed all references to the old `getExtensionNames` method to use the new `getExtensionData` method with the specific key needed. Removed: - Removed the unused `extensionNames` variable and method call from the `getExtensionsPathsFromWslEnv` method. --- src/configuration.ts | 65 +++++++++++++++++++++++++++++++++++--------- src/extension.ts | 6 ++-- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 631a5c4..67186ee 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -22,6 +22,11 @@ export class Configuration { */ private logger: Logger; + /** + * This extension details in the form of a key:value Map object, for ease of use. + */ + private extensionDetails = new Map(); + /** * A key:value Map object of language IDs and their config file paths. */ @@ -61,10 +66,12 @@ export class Configuration { public constructor(logger: Logger) { this.logger = logger; + this.setExtensionData(); + // Always output extension information to channel on activate. - const extensionId = this.getExtensionNames().id; - const extensionVersion = vscode.extensions.getExtension(extensionId)?.packageJSON.version; - this.logger.info(`Extension: ${extensionId} (${extensionVersion})`); + const id = this.getExtensionData("id"); + const version = this.getExtensionData("version"); + this.logger.info(`Extension: ${id} (${version})`); this.findAllLanguageConfigFilePaths(); this.setLanguageConfigDefinitions(); @@ -194,22 +201,56 @@ export class Configuration { } /** - * Get the names and ids of this extension from package.json. + * Get the names, id, and version of this extension from package.json. * - * @returns {object} An object containing the extension id, name, and display name. + * @returns {object} An object containing the extension id, name, display name, and version. */ - public getExtensionNames(): {id: string; name: string; displayName: string} { - const packageJSON = JSON.parse(fs.readFileSync(__dirname + "/../../package.json").toString()); + private getExtensionPackageJsonData(): {id: string; name: string; displayName: string; version: string} { + const packageJSON = this.readJsonFile(__dirname + "/../../package.json"); const displayName: string = packageJSON.displayName; const fullname: string = packageJSON.name; const id: string = `${packageJSON.publisher}.${fullname}`; + const version: string = packageJSON.version; let nameParts = fullname.split("-"); nameParts[0] = "auto"; const name = nameParts.join("-"); - return {id: id, name: name, displayName: displayName}; + return {id: id, name: name, displayName: displayName, version: version}; + } + + /** + * Set the extension data into the extensionDetails Map. + */ + private setExtensionData() { + const extensionPackageJsonData = this.getExtensionPackageJsonData(); + + const id = extensionPackageJsonData.id; + const name = extensionPackageJsonData.name; + const displayName = extensionPackageJsonData.displayName; + const version = extensionPackageJsonData.version; + + const userExtensionsPath = path.join(vscode.extensions.getExtension(id).extensionPath, "../"); + + this.extensionDetails.set("id", id); + this.extensionDetails.set("name", name); + this.extensionDetails.set("displayName", displayName); + this.extensionDetails.set("version", version); + this.extensionDetails.set("userExtensionsPath", userExtensionsPath); + } + + /** + * Get the extension's details. + * + * @param {string} key The key of the specific extension detail to get. + * + * @returns {any} Returns a value of a specific key. + */ + public getExtensionData(key: string): any { + if (this.extensionDetails.has(key)) { + return this.extensionDetails.get(key); + } } /** @@ -218,7 +259,7 @@ export class Configuration { * @returns {vscode.WorkspaceConfiguration} */ public getConfiguration(): vscode.WorkspaceConfiguration { - return vscode.workspace.getConfiguration(this.getExtensionNames().name, null); + return vscode.workspace.getConfiguration(this.getExtensionData("name"), null); } /** @@ -997,7 +1038,7 @@ export class Configuration { */ private handleChangeBladeMultiLineBlock(textEditor: vscode.TextEditor) { let langId = textEditor.document.languageId; - const extensionNames = this.getExtensionNames(); + const extensionName = this.getExtensionData("name"); // Only carry out function if languageId is blade. if (langId === "blade" && !this.isLangIdDisabled(langId)) { @@ -1021,7 +1062,7 @@ export class Configuration { // then output a message to the user. else if (langId == "blade" && this.isLangIdDisabled(langId)) { vscode.window.showInformationMessage( - `Blade is set as disabled in the "${extensionNames.name}.disabledLanguages" setting. The "${extensionNames.name}.bladeOverrideComments" setting will have no affect.`, + `Blade is set as disabled in the "${extensionName}.disabledLanguages" setting. The "${extensionName}.bladeOverrideComments" setting will have no affect.`, "OK" ); @@ -1036,8 +1077,6 @@ export class Configuration { * @returns {Object} An object containing the user and built-in extensions paths. */ private getExtensionsPathsFromWslEnv() { - const extensionNames = this.getExtensionNames(); - /** Built-in Extensions */ // Get the path to the VS Code's exectutable from the VSCODE_CWD environment variable. diff --git a/src/extension.ts b/src/extension.ts index 87da677..20eefd1 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,10 +17,8 @@ export function activate(context: vscode.ExtensionContext) { disposables.push(...configureCommentBlocksDisposable, ...registerCommandsDisposable); - const extensionNames = configuration.getExtensionNames(); - - const extensionName = extensionNames.name; - const extensionDisplayName = extensionNames.displayName; + const extensionName = configuration.getExtensionData("name"); + const extensionDisplayName = configuration.getExtensionData("displayName"); let disabledLangConfig: string[] = configuration.getConfigurationValue("disabledLanguages"); From 50ef691f277f729222f040c9504cbe1202a3593a Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 06:16:23 +0100 Subject: [PATCH 08/14] fix: `logDebugInfo` user extensions path to use `getExtensionData`. Previously we manually created the user extensions path from the home directory env variables and concatenated strings on to it. This is only good if the default extensions directory is used. This will fail if the user has changed the directory location with the CLI `code --extensions-dir ` So to fix, we're now getting the user extensions path from where ever this extension is located. The code for this is defined in `setExtensionData` method as committed in 25fab48. - Changed the construction of the users extensions path in `logDebugInfo` to use the `getExtensionData` method to get the path. - Removed the unneeded home directory variables. --- src/configuration.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 67186ee..b85bd5e 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -1124,12 +1124,9 @@ export class Configuration { "WSL-installed User Extensions Path": path.join(vscode.env.appRoot, "../../", "extensions"), }; } else { - // Get the user home directory from the environment variable: - // `USERPROFILE` on Windows, `HOME` on macOS/Linux. - const userHome = process.env.USERPROFILE || process.env.HOME; extensionsPaths = { "Built-in Extensions Path": builtInExtensionsPath, - "User Extensions Path": path.join(userHome, ".vscode", "extensions"), + "User Extensions Path": this.getExtensionData("userExtensionsPath"), }; } From dec2b9ef1d77c859d31e7b6401871cd4bd04f302 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Thu, 10 Jul 2025 06:24:45 +0100 Subject: [PATCH 09/14] feat: set the built-in extensions path into `extensionDetails` - Moved the code to get the built-in extensions path from `logDebugInfo` in to the `setExtensionData` method. - Added the built-in extensions path to the `extensionDetails` Map in `setExtensionData` method. - Updated `logDebugInfo` method to get the `builtInExtensionsPath` key from the Map using `getExtensionData` method. --- src/configuration.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index b85bd5e..c847747 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -232,12 +232,14 @@ export class Configuration { const version = extensionPackageJsonData.version; const userExtensionsPath = path.join(vscode.extensions.getExtension(id).extensionPath, "../"); + const builtInExtensionsPath = path.join(vscode.env.appRoot, "extensions"); this.extensionDetails.set("id", id); this.extensionDetails.set("name", name); this.extensionDetails.set("displayName", displayName); this.extensionDetails.set("version", version); this.extensionDetails.set("userExtensionsPath", userExtensionsPath); + this.extensionDetails.set("builtInExtensionsPath", builtInExtensionsPath); } /** @@ -1109,7 +1111,7 @@ export class Configuration { private logDebugInfo() { // The path to the built-in extensions. The env variable changes when on WSL. // So we can use it for both Windows and WSL. - const builtInExtensionsPath = path.join(vscode.env.appRoot, "extensions"); + const builtInExtensionsPath = this.getExtensionData("builtInExtensionsPath"); let extensionsPaths = {}; From 5072c553c3bd12f13fc78bd7ad4fa9b6858ba402 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Fri, 11 Jul 2025 03:01:08 +0100 Subject: [PATCH 10/14] change: extension logger info to log the `extensionDetails` Map instead. --- src/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index c847747..fa9d857 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -71,7 +71,7 @@ export class Configuration { // Always output extension information to channel on activate. const id = this.getExtensionData("id"); const version = this.getExtensionData("version"); - this.logger.info(`Extension: ${id} (${version})`); + this.logger.debug(`Extension details:`, this.extensionDetails); this.findAllLanguageConfigFilePaths(); this.setLanguageConfigDefinitions(); From a56f280623785eb15f50141875262c0e15b0ffc2 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Fri, 11 Jul 2025 03:20:16 +0100 Subject: [PATCH 11/14] feat: add WSL paths to `setExtensionData` method. Added: - Added the WSL built-in and user extensions paths code to the `setExtensionData` method and set them into the `extensionDetails` with new Map keys. - Moved the environment variable code to get the WSL-installed user extensions path from the `logDebugInfo` method, and added the `getExtensionData` method call to the log item instead. - Refactored the `getExtensionsPathsFromWslEnv` method into `setExtensionData` method, simplifying the code. Removed: - Removed the now unused `getExtensionsPathsFromWslEnv` method, and changed all references to use the `getExtensionData` with the appropriate key. --- src/configuration.ts | 72 ++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index fa9d857..7555703 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -231,7 +231,13 @@ export class Configuration { const displayName = extensionPackageJsonData.displayName; const version = extensionPackageJsonData.version; - const userExtensionsPath = path.join(vscode.extensions.getExtension(id).extensionPath, "../"); + // The path to the user extensions. + const userExtensionsPath = isWSL + ? path.join(vscode.env.appRoot, "../../", "extensions") + : path.join(vscode.extensions.getExtension(id).extensionPath, "../"); + + // The path to the built-in extensions. + // This env variable changes when on WSL to it's WSL-built-in extensions path. const builtInExtensionsPath = path.join(vscode.env.appRoot, "extensions"); this.extensionDetails.set("id", id); @@ -240,6 +246,18 @@ export class Configuration { this.extensionDetails.set("version", version); this.extensionDetails.set("userExtensionsPath", userExtensionsPath); this.extensionDetails.set("builtInExtensionsPath", builtInExtensionsPath); + + if (isWsl) { + // Get the root path to VS Code from the env variable, and use it to get + // the Windows built-in extensions. + const windowsBuiltInExtensionsPathFromWsl = path.join(process.env.VSCODE_CWD, "resources/app/extensions"); + + // Get the Windows user extensions path from env variable. + const windowsUserExtensionsPathFromWsl = path.dirname(process.env.VSCODE_WSL_EXT_LOCATION); + + this.extensionDetails.set("WindowsUserExtensionsPathFromWsl", windowsUserExtensionsPathFromWsl); + this.extensionDetails.set("WindowsBuiltInExtensionsPathFromWsl", windowsBuiltInExtensionsPathFromWsl); + } } /** @@ -351,12 +369,13 @@ export class Configuration { // If running in WSL... if (isWsl) { - // Get the Windows built-in and user extensions paths from WSL environment variables. - const {builtInExtensionsPathFromWsl, userExtensionsPathFromWsl} = this.getExtensionsPathsFromWslEnv(); + // Get the Windows user and built-in extensions paths. + const windowsUserExtensionsPath = this.getExtensionData("WindowsUserExtensionsPathFromWsl"); + const windowsBuiltInExtensionsPath = this.getExtensionData("WindowsBuiltInExtensionsPathFromWsl"); // Read the paths and create arrays of the extensions. - const builtInExtensions = this.readExtensionsFromDirectory(builtInExtensionsPathFromWsl); - const userExtensions = this.readExtensionsFromDirectory(userExtensionsPathFromWsl); + const builtInExtensions = this.readExtensionsFromDirectory(windowsBuiltInExtensionsPath); + const userExtensions = this.readExtensionsFromDirectory(windowsUserExtensionsPath); // Combine the built-in and user extensions into the extensions array. extensions.push(...builtInExtensions, ...userExtensions); @@ -1073,38 +1092,6 @@ export class Configuration { } } - /** - * Gets the user and built-in extensions paths on Windows from WSL environment variables. - * - * @returns {Object} An object containing the user and built-in extensions paths. - */ - private getExtensionsPathsFromWslEnv() { - /** Built-in Extensions */ - - // Get the path to the VS Code's exectutable from the VSCODE_CWD environment variable. - // The variable will be a path like: - // "/mnt/c/Users/USERNAME/AppData/Local/Programs/Microsoft VS Code". - const vscodePathFromWsl = process.env.VSCODE_CWD; - // Append "resources/app/extensions" to the base path to form the path to the - // built-in extensions. - const builtInExtensionsPathFromWsl = path.join(vscodePathFromWsl, "resources/app/extensions"); - - /** User Extensions */ - - // Get the user extensions path from VSCODE_WSL_EXT_LOCATION env variable. - // If it's not set, then use an empty string. - // The variable will be a path like: - // "/mnt/c/Users/USERNAME/.vscode/extensions/ms-vscode-remote.remote-wsl-0.99.0". - // So we just need to return the directory name like: - // "/mnt/c/Users/USERNAME/.vscode/extensions/" - const userExtensionsPathFromWsl = path.dirname(process.env.VSCODE_WSL_EXT_LOCATION); - - return { - builtInExtensionsPathFromWsl, - userExtensionsPathFromWsl, - }; - } - /** * Logs the environment, configuration settings, and language configs for debugging purposes. */ @@ -1116,14 +1103,15 @@ export class Configuration { let extensionsPaths = {}; if (isWsl) { - // Get the Windows user and built-in extensions paths on Windows from WSL environment variables. - const {builtInExtensionsPathFromWsl, userExtensionsPathFromWsl} = this.getExtensionsPathsFromWslEnv(); + // Get the Windows user and built-in extensions paths. + const windowsUserExtensionsPath = this.getExtensionData("WindowsUserExtensionsPathFromWsl"); + const windowsBuiltInExtensionsPath = this.getExtensionData("WindowsBuiltInExtensionsPathFromWsl"); extensionsPaths = { - "Windows-installed Built-in Extensions Path": builtInExtensionsPathFromWsl, - "Windows-installed User Extensions Path": userExtensionsPathFromWsl, + "Windows-installed Built-in Extensions Path": windowsBuiltInExtensionsPath, + "Windows-installed User Extensions Path": windowsUserExtensionsPath, "WSL-installed Built-in Extensions Path": builtInExtensionsPath, - "WSL-installed User Extensions Path": path.join(vscode.env.appRoot, "../../", "extensions"), + "WSL-installed User Extensions Path": this.getExtensionData("userExtensionsPath"), }; } else { extensionsPaths = { From 69f4bf603cae44d71dd9ab85762f260126243882 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Fri, 11 Jul 2025 03:22:39 +0100 Subject: [PATCH 12/14] fix: `readExtensionsFromDirectory` to skip directories starting with a dot. --- src/configuration.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/configuration.ts b/src/configuration.ts index 7555703..1405cdb 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -523,6 +523,11 @@ export class Configuration { // If the extensionName is a directory... if (fs.statSync(extensionPath).isDirectory()) { + // If the extensionName starts with a dot, skip it. + if (extensionName.startsWith(".")) { + return; + } + // Get the package.json file path. const packageJSONPath = path.join(extensionPath, "package.json"); From f6f85feb0b1cc48b00be8c1899d6ba319a667dcb Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Fri, 11 Jul 2025 03:34:23 +0100 Subject: [PATCH 13/14] fix: "includes is not a function" error when `lineComment` is an object. In the `setSingleLineCommentLanguageDefinitions` method, it uses the `String.includes` method to detect when the `lineComment` string has `includes` a semi-colon - ;. Apparently the lineComment key in the language config can be either a string or an object. The object has a `comment` key, among others. But because the `includes` method is on the String prototype, when its used on the object, it errors out with "lineComment.includes is not a function". The only language to do this was "makefile". To fix: - Added a check to see if the `lineComment` is an object with a `comment` key inside, if it does then use the string value of the `comment` key. Otherwise, it will use the string value of the `lineComment`. --- src/configuration.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/configuration.ts b/src/configuration.ts index 1405cdb..bf7f918 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -622,16 +622,24 @@ export class Configuration { // If the config object has own property of comments AND the comments key has // own property of lineComment... if (Object.hasOwn(config, "comments") && Object.hasOwn(config.comments, "lineComment")) { + let lineComment = config.comments.lineComment; + + // Line comments can be a string or an object with a "comment" key. + // If the lineComment is an object, get the "comment" key value. + if (Object.hasOwn(lineComment, "comment")) { + lineComment = lineComment.comment; + } + // If the lineComment is "//"... - if (config.comments.lineComment === "//") { + if (lineComment === "//") { style = "//"; } // If the lineComment is "#"... - else if (config.comments.lineComment === "#") { + else if (lineComment === "#") { style = "#"; } // If the lineComment includes a ";" (; or ;;)... - else if (config.comments.lineComment.includes(";")) { + else if (lineComment.includes(";")) { style = ";"; } From ee50f3d1983df754745f7d67eed9b34ed9ef3e71 Mon Sep 17 00:00:00 2001 From: yCodeTech Date: Sat, 12 Jul 2025 01:06:51 +0100 Subject: [PATCH 14/14] fix: TS compile error: Cannot find name 'isWSL'. Did you mean 'isWsl'? https://github.com/yCodeTech/auto-comment-blocks/actions/runs/16210470528 --- src/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/configuration.ts b/src/configuration.ts index bf7f918..de1cdf2 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -232,7 +232,7 @@ export class Configuration { const version = extensionPackageJsonData.version; // The path to the user extensions. - const userExtensionsPath = isWSL + const userExtensionsPath = isWsl ? path.join(vscode.env.appRoot, "../../", "extensions") : path.join(vscode.extensions.getExtension(id).extensionPath, "../");