Skip to content
Open
Changes from 1 commit
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
19 changes: 14 additions & 5 deletions packages/cli/src/config/extensions/extensionEnablement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export class ExtensionEnablementManager {
// If non-empty, this overrides all other extension configuration and enables
// only the ones in this list.
private enabledExtensionNamesOverride: string[];
private cachedConfig: AllExtensionsEnablementConfig | undefined;

constructor(enabledExtensionNames?: string[]) {
this.configDir = ExtensionStorage.getUserExtensionsDir();
Expand Down Expand Up @@ -177,29 +178,37 @@ export class ExtensionEnablementManager {
}

readConfig(): AllExtensionsEnablementConfig {
if (this.cachedConfig) {
return this.cachedConfig;
}

try {
const content = fs.readFileSync(this.configFilePath, 'utf-8');
return JSON.parse(content);
this.cachedConfig = JSON.parse(content);
return this.cachedConfig!;
} catch (error) {
if (
error instanceof Error &&
'code' in error &&
error.code === 'ENOENT'
(error as { code: string }).code === 'ENOENT'
) {
return {};
this.cachedConfig = {};
return this.cachedConfig;
}
coreEvents.emitFeedback(
'error',
'Failed to read extension enablement config.',
`Failed to read extension enablement config at ${this.configFilePath}.`,
error,
);
return {};
this.cachedConfig = {};
return this.cachedConfig;
}
Comment on lines 189 to 205
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The catch block can be refactored to be more concise and to better align with the PR's goal of improving error reporting for syntax errors. The current implementation contains duplicated code for caching an empty configuration and uses a generic error message for parsing failures.

By restructuring this block, we can:

  1. Eliminate code duplication for caching an empty config (this.cachedConfig = {}).
  2. Provide a more specific and helpful error message when JSON.parse fails due to a SyntaxError.
  3. Consistently cache an empty config on any read failure to prevent error spam, while selectively logging errors (i.e., not logging for a missing file, which is an expected condition).
Suggested change
} catch (error) {
if (
error instanceof Error &&
'code' in error &&
error.code === 'ENOENT'
(error as { code: string }).code === 'ENOENT'
) {
return {};
this.cachedConfig = {};
return this.cachedConfig;
}
coreEvents.emitFeedback(
'error',
'Failed to read extension enablement config.',
`Failed to read extension enablement config at ${this.configFilePath}.`,
error,
);
return {};
this.cachedConfig = {};
return this.cachedConfig;
}
} catch (error) {
const isEnoent =
error instanceof Error &&
'code' in error &&
(error as { code: string }).code === 'ENOENT';
if (!isEnoent) {
let message = `Failed to read or parse extension enablement config at ${this.configFilePath}.`;
if (error instanceof SyntaxError) {
message += `\nDetails: ${error.message}`;
}
coreEvents.emitFeedback('error', message, error);
}
this.cachedConfig = {};
return this.cachedConfig;
}

}

writeConfig(config: AllExtensionsEnablementConfig): void {
fs.mkdirSync(this.configDir, { recursive: true });
fs.writeFileSync(this.configFilePath, JSON.stringify(config, null, 2));
this.cachedConfig = config;
}

enable(
Expand Down