Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 10 additions & 19 deletions src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import isWsl from "is-wsl";
import {IPackageJson} from "package-json-type";

import {Rules} from "./rules";
import {Logger} from "./logger";
import {logger} from "./logger";
import * as utils from "./utils";
import {ExtensionData} from "./extensionData";

Expand All @@ -17,13 +17,6 @@ export class Configuration {
* Properties *
**************/

/**
* The Logger class instance for logging messages to the Output Channel.
*
* @type {Logger}
*/
private logger: Logger;

/**
* This extension data class instance.
* @type {ExtensionData}
Expand Down Expand Up @@ -78,11 +71,9 @@ export class Configuration {
* Methods *
***********/

public constructor(logger: Logger) {
this.logger = logger;

public constructor() {
// Always output extension information to channel on activate.
this.logger.debug(`Extension details:`, this.extensionData.getAll());
logger.debug(`Extension details:`, this.extensionData.getAll());

this.findAllLanguageConfigFilePaths();
this.setLanguageConfigDefinitions();
Expand Down Expand Up @@ -861,7 +852,7 @@ export class Configuration {
this.normalizeOnEnterRules(langConfig.onEnterRules);
}

this.logger.debug(`The language config for ${langId}:`, langConfig);
logger.debug(`The language config for ${langId}:`, langConfig);

return vscode.languages.setLanguageConfiguration(langId, langConfig);
}
Expand Down Expand Up @@ -1004,16 +995,16 @@ export class Configuration {
},
"Other System Env Variables": process.env,
};
this.logger.debug("Environment:", env);
logger.debug("Environment:", env);

// Log the extension's user configuration settings.
this.logger.debug("Configuration settings:", this.getConfiguration());
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:", utils.readJsonFile(this.multiLineLangDefinitionFilePath));
this.logger.debug("The supported languages for single-line blocks:", utils.readJsonFile(this.singleLineLangDefinitionFilePath));
logger.debug("The language config filepaths found are:", this.languageConfigFilePaths);
logger.debug("The language configs found are:", this.languageConfigs);
logger.debug("The supported languages for multi-line blocks:", utils.readJsonFile(this.multiLineLangDefinitionFilePath));
logger.debug("The supported languages for single-line blocks:", utils.readJsonFile(this.singleLineLangDefinitionFilePath));
}

/**
Expand Down
5 changes: 2 additions & 3 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
import * as vscode from "vscode";

import {Configuration} from "./configuration";
import {Logger} from "./logger";
import {logger} from "./logger";
import {ExtensionData} from "./extensionData";

const logger = new Logger();
const extensionData = new ExtensionData();
logger.setupOutputChannel();
let configuration = new Configuration(logger);
let configuration = new Configuration();

const disposables: vscode.Disposable[] = [];

Expand Down
13 changes: 12 additions & 1 deletion src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {OutputChannel, window} from "vscode";
*
* @class Logger
*/
export class Logger {
class Logger {
/**************
* Properties *
**************/
Expand Down Expand Up @@ -61,6 +61,15 @@ export class Logger {
this.outputChannel.dispose();
}

/**
* Show the output channel to the user.
*/
public showChannel(): void {
if (this.outputChannel) {
this.outputChannel.show();
}
}

/**
* Sends a basic info log to the output channel.
*
Expand Down Expand Up @@ -163,3 +172,5 @@ export class Logger {
return value;
}
}

export const logger = new Logger();
64 changes: 62 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,75 @@
import * as fs from "node:fs";
import * as jsonc from "jsonc-parser";
import {logger} from "./logger";
import {window} from "vscode";

/**
* Read the file and parse the JSON.
*
* @param {string} filepath The path of the file.
*
* @returns The file content.
* @returns {any} The JSON file content as an object.
* @throws Will throw an error if the JSON file cannot be parsed.
*/
export function readJsonFile(filepath: string): any {
return jsonc.parse(fs.readFileSync(filepath).toString());
const jsonErrors: jsonc.ParseError[] = [];

const fileContent = fs.readFileSync(filepath).toString();
const jsonContents = jsonc.parse(fileContent, jsonErrors) ?? {};

if (jsonErrors.length > 0) {
const errorMessages = constructJsonParseErrorMsg(filepath, fileContent, jsonErrors);
const errorMsg = "Failed to parse a required JSON file";
const error = new Error(`${errorMsg}: "${filepath}"\n\n\tParse Errors:\n\n${errorMessages}\n\tStack Trace:`);

logger.error(error.stack);

window
.showErrorMessage(
`${errorMsg}. The extension cannot continue. Please check the "Auto Comment Blocks" Output Channel for errors.`,
"OK",
"Open Output Channel"
)
.then((selection) => {
if (selection === "Open Output Channel") {
logger.showChannel();
}
});

throw error;
}

return jsonContents;
}

/**
* Construct detailed JSON parse error messages with file, line, and column information.
*
* @param {string} filepath The path of the file.
* @param {string} fileContent The content of the file.
* @param {jsonc.ParseError[]} jsonErrors The JSON parse errors.
*
* @returns {string} The constructed error message.
*/
function constructJsonParseErrorMsg(filepath: string, fileContent: string, jsonErrors: jsonc.ParseError[]): string {
return jsonErrors
.map((err, i) => {
// Get the error name from the numeric error code.
// The name is PascalCased, so we need to format it by adding spaces
// before capital letters for readability.
const errorName = jsonc
.printParseErrorCode(err.error)
.replace(/([A-Z])/g, " $1")
.trim();

// Calculate line and column numbers from the error offset.
const lineNumber = fileContent.substring(0, err.offset).split("\n").length;
const columnNumber = err.offset - fileContent.lastIndexOf("\n", err.offset - 1);

// Return the formatted error message.
return `\tError ${i + 1} - ${errorName} at "${filepath}:${lineNumber}:${columnNumber}"\n`;
})
.join("\n");
}

/**
Expand Down