Skip to content

Run CodeRabbit on the entire codebase#2

Open
Parsa2820 wants to merge 13 commits intotest/code-rabbit-emptyfrom
test/code-rabbit
Open

Run CodeRabbit on the entire codebase#2
Parsa2820 wants to merge 13 commits intotest/code-rabbit-emptyfrom
test/code-rabbit

Conversation

@Parsa2820
Copy link
Owner

@Parsa2820 Parsa2820 commented Dec 21, 2025

@coderabbitai full review

Summary by CodeRabbit

  • New Features

    • Added transaction status cycling command (Ctrl+Shift+T / Cmd+Shift+T on Mac)
    • Implemented account name auto-completion
    • Added automatic document formatting with aligned padding for ledger entries
  • Documentation

    • Updated changelog with version history
    • Added example ledger file with sample accounts

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

Walkthrough

This PR establishes a complete VS Code extension for the Ledger language, including project scaffolding, build tooling, extension lifecycle management, document formatting, account auto-completion, and transaction status cycling functionality. The extension activates to register formatters, completion providers, and keyboard-bound commands for ledger file editing.

Changes

Cohort / File(s) Summary
VSCode Workspace Configuration
.vscode/launch.json, .vscode/settings.json, .vscode/tasks.json, .vscode/extensions.json
Configures VS Code debugging, editor settings, build task (npm watch with TypeScript compiler matcher), and recommended extensions (ESLint, Extension Test Runner). Launch config renames to "Run Extension" and adds outFiles and preLaunchTask for compiled JS. Settings hide and exclude the "out" folder and disable auto TypeScript detection.
Build & Tooling Configuration
tsconfig.json, eslint.config.mjs, .vscode-test.mjs
Establishes TypeScript compilation with strict mode targeting ES2022, ESLint rules for TypeScript with naming conventions and stylistic warnings, and VS Code test CLI configuration pointing to out/test/**/*.test.js.
Ignore Patterns
.gitignore, .vscodeignore
Updates .gitignore to ignore out/, dist/, and .vscode-test/ while removing .env; adds comprehensive patterns to .vscodeignore for source files, configs, maps, and test files.
Project Metadata
package.json, CHANGELOG.md, LICENSE, README.md
Version bumped to 0.0.3 with repository, publisher, and main entry added; categories extended to include "Formatters"; scripts added for build/test/lint; devDependencies updated with TypeScript and VS Code tools; changelog populated with versions 0.0.1–0.0.3; MIT license added; README trimmed to minimal reference.
Extension Source Code
src/extension.ts, src/formatter.ts, src/commands/index.ts, src/commands/transactionCommands.ts, src/completion.ts
Implements extension activation with formatter registration (pads account names and amounts), completion provider (loads and suggests account names from configured files), command registration, and transaction status cycling (toggles "!" ↔ "*" on current line).
Example Files
examples/accounts.ledger
Provides sample ledger accounts file with six account definitions (Assets, Expenses, Income, Liabilities, Equity).

Sequence Diagram

sequenceDiagram
    participant VSCode
    participant Extension
    participant Formatter as LedgerDocumentFormatter
    participant Completion as LedgerAccountCompletion
    participant Commands as Command Handler
    participant FileSystem as File System

    VSCode->>Extension: activate(context)
    Note over Extension: Extension initialization
    Extension->>Formatter: registerDocumentFormattingEditProvider("ledger")
    Extension->>Completion: new LedgerAccountCompletion()
    Completion->>FileSystem: loadAccountFile (constructor)
    FileSystem-->>Completion: account names loaded
    Extension->>Completion: registerCompletionItemProvider("ledger")
    Extension->>Commands: registerCommands(context)
    Commands->>VSCode: subscribe to ledger.transactionStatusCycle
    Extension-->>VSCode: ✓ extension activated

    rect rgba(100, 200, 100, 0.1)
    Note over VSCode,Commands: User edits ledger file
    VSCode->>Formatter: provideDocumentFormattingEdits(document)
    Formatter->>Formatter: parse & pad account lines
    Formatter-->>VSCode: TextEdit[] (formatted lines)
    end

    rect rgba(100, 150, 200, 0.1)
    Note over VSCode,Completion: User triggers completion
    VSCode->>Completion: provideCompletionItems(position)
    Completion-->>VSCode: CompletionItem[] (accounts)
    end

    rect rgba(200, 100, 100, 0.1)
    Note over VSCode,Commands: User presses Ctrl+Shift+T
    VSCode->>Commands: ledger.transactionStatusCycle
    Commands->>VSCode: getActiveEditor() → editor
    Commands->>VSCode: replace "!" ↔ "*" on current line
    Commands-->>VSCode: ✓ status toggled
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • src/completion.ts: Requires careful review of file path resolution logic (handling ~, relative paths, workspace roots), async file loading, regex pattern for account extraction, and error handling with fallbacks.
  • src/formatter.ts: Account line parsing, duplicate empty line removal, and padding calculation across variable-length account names and amounts need verification for edge cases.
  • package.json: Comprehensive manifest updates including new commands, keybindings, configuration schema, scripts, and dependencies should be validated for consistency and correctness.
  • Multiple configuration files: Cross-cutting validation needed across .vscode/ files, tsconfig.json, eslint.config.mjs, and .vscode-test.mjs to ensure build, test, and debug workflows integrate correctly.

Poem

🐰 A ledger so fine, now formatted with care,
Account names complete, with auto-complete flair!
Toggle transactions with Ctrl+Shift+T delight,
Bunny's extension hops in to make ledgers just right! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The pull request title 'Run CodeRabbit on the entire codebase' is vague and does not accurately describe the actual changes, which involve adding VS Code extension configuration, TypeScript setup, ESLint configuration, ledger example files, and extension functionality for a ledger CLI VS Code extension. Use a descriptive title that reflects the main purpose of the changes, such as 'Add VS Code ledger extension with formatting, completion, and transaction status cycling' or 'Initial setup for ledger CLI VS Code extension.'
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test/code-rabbit

Comment @coderabbitai help to get the list of available commands and usage tips.

@Parsa2820
Copy link
Owner Author

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Dec 21, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (5)
README.md (1)

1-12: Consider expanding documentation.

The README is minimal. Consider adding:

  • Installation instructions
  • Usage examples for the formatter and auto-completion
  • Configuration options (e.g., ledger.accountFiles setting mentioned in completion.ts)
  • Keybinding documentation for the transaction status cycle command
src/commands/transactionCommands.ts (1)

3-17: Consider returning the Thenable from editor.edit.

The editor.edit() call returns a Thenable<boolean> that indicates success. While not critical for this use case, returning it would allow callers to chain or await the operation if needed.

🔎 Optional: return the edit result
-export function transactionStatusCycleHandler() {
+export function transactionStatusCycleHandler(): Thenable<boolean> | undefined {
 	const editor = vscode.window.activeTextEditor;
 	if (editor) {
 		const currentLine = editor.document.lineAt(editor.selection.active.line);
 
 		if (currentLine.text.includes("!")) {
-			editor.edit(editBuilder => {
+			return editor.edit(editBuilder => {
 				editBuilder.replace(currentLine.range, currentLine.text.replace("!", "*"));
 			});
 		} else if (currentLine.text.includes("*")) {
-			editor.edit(editBuilder => {
+			return editor.edit(editBuilder => {
 				editBuilder.replace(currentLine.range, currentLine.text.replace("*", "!"));
 			});
 		}
 	}
+	return undefined;
 }
src/extension.ts (1)

8-8: Consider using OutputChannel for production logging.

console.log works for development, but for production extensions, using vscode.window.createOutputChannel() provides a dedicated, user-accessible log panel.

src/formatter.ts (1)

77-92: Consider caching the regex pattern and expanding pattern coverage.

The pattern is recompiled on every call to isAccountLine and extractAccountLineEntry. For large documents, this creates unnecessary overhead. Consider caching the pattern as a class property.

Additionally, a few pattern observations:

  • The closing bracket/paren [\]\)]? is outside the capture group, so accounts like [Assets:Bank] will be captured as [Assets:Bank (missing closing bracket).
  • The amount pattern only handles $ currency symbol and requires exactly 2 decimal places.
🔎 Proposed fix to cache the pattern
 export class LedgerDocumentFormatter implements vscode.DocumentFormattingEditProvider {
+  private readonly accountLinePattern: RegExp;
+
+  constructor() {
+    const whitespacePattern = /\s{2,}/;
+    const accountNamePattern = /(?<account>[\[\(]?[A-Za-z0-9:_\-]+[\]\)]?)/;
+    const amountPattern = /(?<amount>[\-+]?[\$€£]?[0-9,]+(?:\.[0-9]+)?\s+[A-Z]{3})?/;
+    const commentPattern = /\s*(?<comment>[;#%\|\*].*)?/;
+    this.accountLinePattern = new RegExp(
+      "^" +
+      whitespacePattern.source +
+      accountNamePattern.source +
+      "(" + whitespacePattern.source +
+      amountPattern.source +
+      ")?" +
+      commentPattern.source +
+      "$"
+    );
+  }
+
   // ... update methods to use this.accountLinePattern
src/completion.ts (1)

79-88: Consider aligning account name pattern with the formatter.

The accountNamePattern here has the same issue as in the formatter—closing brackets/parens are outside the capture group. If both files need to parse account names, consider extracting a shared utility to ensure consistency.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 466011c and b088742.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (19)
  • .gitignore (1 hunks)
  • .vscode-test.mjs (1 hunks)
  • .vscode/extensions.json (1 hunks)
  • .vscode/launch.json (1 hunks)
  • .vscode/settings.json (1 hunks)
  • .vscode/tasks.json (1 hunks)
  • .vscodeignore (1 hunks)
  • CHANGELOG.md (1 hunks)
  • LICENSE (1 hunks)
  • README.md (1 hunks)
  • eslint.config.mjs (1 hunks)
  • examples/accounts.ledger (1 hunks)
  • package.json (1 hunks)
  • src/commands/index.ts (1 hunks)
  • src/commands/transactionCommands.ts (1 hunks)
  • src/completion.ts (1 hunks)
  • src/extension.ts (1 hunks)
  • src/formatter.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/extension.ts (3)
src/formatter.ts (1)
  • LedgerDocumentFormatter (3-93)
src/completion.ts (1)
  • LedgerAccountCompletion (3-89)
src/commands/index.ts (1)
  • registerCommands (4-10)
src/commands/index.ts (1)
src/commands/transactionCommands.ts (1)
  • transactionStatusCycleHandler (3-18)
🪛 LanguageTool
CHANGELOG.md

[grammar] ~16-~16: Use a hyphen to join words.
Context: ... - 2025-09-17 - Implemented account auto completion

(QB_NEW_EN_HYPHEN)

🔇 Additional comments (15)
LICENSE (1)

1-21: LGTM!

The MIT License is correctly formatted and complete.

.vscode/extensions.json (1)

1-8: LGTM!

The extension recommendations are appropriate for a TypeScript-based VS Code extension project with ESLint and testing infrastructure.

.vscodeignore (1)

1-11: LGTM!

The exclusion patterns are appropriate for packaging a VS Code extension. Source files, configuration, and development artifacts are correctly excluded to ensure a lean published package.

.vscode/tasks.json (1)

1-20: LGTM!

The watch task configuration is standard for TypeScript projects. The background task setup with $tsc-watch problem matcher and default build group assignment is appropriate for extension development.

.vscode-test.mjs (1)

1-5: LGTM!

The test configuration correctly targets compiled test files and follows the standard VS Code extension test setup pattern.

.gitignore (1)

1-5: No actionable concern regarding .env removal.

The repository doesn't use .env files for configuration or secrets. Analysis shows:

  • No .env files exist in the codebase
  • No dotenv dependency or secret management patterns
  • The only process.env usage accesses standard system variables (HOME/USERPROFILE)
  • Git history shows no evidence that .env was previously in .gitignore

This is a VS Code extension project with no environment-based secrets to protect. The .gitignore changes are appropriate for the project's actual dependencies.

Likely an incorrect or invalid review comment.

tsconfig.json (1)

1-17: Configuration looks good for a VS Code extension.

The TypeScript configuration is well-suited for VS Code extension development with strict mode enabled. Consider enabling the commented-out checks (noImplicitReturns, noFallthroughCasesInSwitch, noUnusedParameters) for stricter type safety, though this is optional.

.vscode/launch.json (1)

1-21: LGTM!

The launch configuration correctly references the compiled output directory (out/**/*.js) and ensures the build task runs before launching. This aligns with the TypeScript configuration.

src/commands/index.ts (1)

1-10: LGTM!

Clean command registration pattern with proper disposal through context.subscriptions. The module structure separating command registration from handler implementation promotes maintainability.

examples/accounts.ledger (1)

1-6: LGTM!

Good sample ledger file covering the standard account hierarchy. This provides a reasonable default for the account completion feature.

.vscode/settings.json (1)

1-11: LGTM!

Appropriate workspace settings for extension development. The out folder is visible in the explorer (for debugging purposes) but excluded from search to avoid noise from compiled files. Disabling TSC auto-detection is correct since build tasks are provided via npm scripts.

src/extension.ts (1)

6-17: LGTM!

Clean activation pattern with proper disposal of all registered providers. All subscriptions are correctly pushed to context.subscriptions.

src/completion.ts (2)

27-38: LGTM!

Path resolution logic handles home directory expansion and relative paths correctly across platforms. Minor edge case: relative paths without a workspace folder will be passed through unchanged and may fail during file read, but this is handled gracefully by the try-catch in loadAccountFile.


40-64: LGTM!

File loading with proper error handling and account extraction logic is well-structured. The same pattern caching optimization mentioned for the formatter could apply to getAccountDeclarationPattern() here.

package.json (1)

75-85: DevDependency versions are valid; consider updating to latest releases.

Specified versions are all functional. @types/vscode (1.105.0), typescript (5.9), and @vscode/test-cli (0.0.12) have newer releases available, though the caret constraints in package.json will pull appropriate updates on next install.

- Added transaction status cycling command

## [0.0.3] - 2025-09-17
- Implemented account auto completion No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider hyphenating "auto completion" for grammatical correctness.

The phrase "account auto completion" should be hyphenated as "account auto-completion" per standard English grammar rules for compound modifiers.

🔎 Suggested fix
-## [0.0.3] - 2025-09-17
-- Implemented account auto completion
+## [0.0.3] - 2025-09-17
+- Implemented account auto-completion
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- Implemented account auto completion
- Implemented account auto-completion
🧰 Tools
🪛 LanguageTool

[grammar] ~16-~16: Use a hyphen to join words.
Context: ... - 2025-09-17 - Implemented account auto completion

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In CHANGELOG.md around line 16, the phrase "Implemented account auto completion"
should be hyphenated as a compound modifier; update the line to read
"Implemented account auto-completion".

Comment on lines +4 to +28
export default [{
files: ["**/*.ts"],
}, {
plugins: {
"@typescript-eslint": typescriptEslint,
},

languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: "module",
},

rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],

curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}]; No newline at end of file
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix ESLint configuration structure to properly scope TypeScript rules.

The configuration has a structural issue: the first object only specifies files without any rules, while the second object contains all the rules but lacks a files property. This causes the TypeScript rules to apply to all files instead of just TypeScript files, and the first object is effectively useless.

In ESLint flat config, each object should be a complete, self-contained configuration.

🔎 Proposed fix: Merge into a single configuration object
-export default [{
-    files: ["**/*.ts"],
-}, {
+export default [{
+    files: ["**/*.ts"],
     plugins: {
         "@typescript-eslint": typescriptEslint,
     },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default [{
files: ["**/*.ts"],
}, {
plugins: {
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: "module",
},
rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],
curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}];
export default [{
files: ["**/*.ts"],
plugins: {
"@typescript-eslint": typescriptEslint,
},
languageOptions: {
parser: tsParser,
ecmaVersion: 2022,
sourceType: "module",
},
rules: {
"@typescript-eslint/naming-convention": ["warn", {
selector: "import",
format: ["camelCase", "PascalCase"],
}],
curly: "warn",
eqeqeq: "warn",
"no-throw-literal": "warn",
semi: "warn",
},
}];
🤖 Prompt for AI Agents
In eslint.config.mjs around lines 4 to 28, the config splits `files` into the
first object and all plugins/rules into the second, causing TypeScript rules to
be applied globally; fix this by merging them into a single config object that
includes files: ["**/*.ts"], plugins, languageOptions (parser, ecmaVersion,
sourceType) and the rules so the TypeScript-specific rules only apply to
TypeScript files.

@@ -2,24 +2,85 @@
"name": "ledger-cli",
"displayName": "ledger-cli",
"description": "ledger-cli.org lanugage support",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Typo in description.

"lanugage" should be "language".

-  "description": "ledger-cli.org lanugage support",
+  "description": "ledger-cli.org language support",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"description": "ledger-cli.org lanugage support",
"description": "ledger-cli.org language support",
🤖 Prompt for AI Agents
In package.json around line 4, the description field contains a typo "lanugage";
update the string to use the correct spelling "language" so the description
reads "ledger-cli.org language support".

Comment on lines +45 to +52
"keybindings": [
{
"command": "ledger.transactionStatusCycle",
"key": "ctrl+shift+t",
"mac": "cmd+shift+t",
"when": "editorTextFocus && resourceExtname == '.ledger'"
}
],
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential keybinding conflict with VS Code default.

ctrl+shift+t / cmd+shift+t is the default keybinding for "Reopen Closed Tab" in VS Code. While the when clause restricts this to ledger files, users may still expect the default behavior when editing these files.

Consider using a less common keybinding or documenting this override.

🤖 Prompt for AI Agents
In package.json around lines 45 to 52, the extension binds ctrl+shift+t /
cmd+shift+t which conflicts with VS Code's default "Reopen Closed Tab" binding
even though it's scoped to .ledger files; change the keybinding to a less common
combination (e.g., include Alt/Option or use a chord) or remove it and add
documentation noting the override so users aren't surprised, and update
package.json's keybindings entry and README accordingly.

See [CHANGELOG.md](CHANGELOG.md)

**Enjoy!**
This is a change just to test CodeRabbit
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove test content before merging.

This line appears to be temporary test content added for the PR and should be removed.

🤖 Prompt for AI Agents
In README.md around line 13, there is temporary test content ("This is a change
just to test CodeRabbit") that must be removed before merging; delete that line
(or replace it with the intended README content) so the file contains only the
final documentation text.

Comment on lines +8 to +16
if (currentLine.text.includes("!")) {
editor.edit(editBuilder => {
editBuilder.replace(currentLine.range, currentLine.text.replace("!", "*"));
});
} else if (currentLine.text.includes("*")) {
editor.edit(editBuilder => {
editBuilder.replace(currentLine.range, currentLine.text.replace("*", "!"));
});
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential edge-case: unintended replacements in line content.

String.replace only replaces the first occurrence, but ! or * might appear in transaction descriptions or comments (e.g., 2024/01/01 ! Buy *special* item). Consider targeting only the transaction status position (typically after the date) using a regex pattern.

Additionally, if a line contains both ! and *, the ! branch always takes precedence, which may not cycle as expected.

🔎 Suggested improvement using a targeted regex
 export function transactionStatusCycleHandler() {
 	const editor = vscode.window.activeTextEditor;
 	if (editor) {
 		const currentLine = editor.document.lineAt(editor.selection.active.line);
+		// Match status marker after date pattern (e.g., "2024/01/01 !" or "2024-01-01 *")
+		const statusPattern = /^(\d{4}[/-]\d{2}[/-]\d{2}\s+)([!*])/;
+		const match = currentLine.text.match(statusPattern);
 
-		if (currentLine.text.includes("!")) {
-			editor.edit(editBuilder => {
-				editBuilder.replace(currentLine.range, currentLine.text.replace("!", "*"));
-			});
-		} else if (currentLine.text.includes("*")) {
+		if (match) {
+			const newStatus = match[2] === "!" ? "*" : "!";
 			editor.edit(editBuilder => {
-				editBuilder.replace(currentLine.range, currentLine.text.replace("*", "!"));
+				editBuilder.replace(currentLine.range, currentLine.text.replace(statusPattern, `$1${newStatus}`));
 			});
 		}
 	}
 }
🤖 Prompt for AI Agents
In src/commands/transactionCommands.ts around lines 8 to 16, the current code
naively calls String.replace on the whole line which only changes the first
occurrence anywhere (and always prefers the "!" branch if both symbols exist),
causing unintended replacements in descriptions; change the logic to locate the
transaction status character specifically (e.g. with a regex that matches the
date at line start and captures the status symbol immediately after the date,
such as /^\s*\d{4}\/\d{2}\/\d{2}\s+([!*])/) then replace only that captured
group (toggle '!' to '*' and '*' to '!'), handle the case where both symbols
exist by targeting the status position rather than scanning the whole line, and
perform a single editor.edit call that replaces the exact range for that match.

Comment on lines +6 to +17
constructor() {
const defaultAccountsFile = vscode.Uri.joinPath(vscode.extensions.getExtension('parsa2820.ledger-cli')!.extensionUri, 'examples', 'accounts.ledger').fsPath;
const accountFiles = vscode.workspace.getConfiguration('ledger').get<string[]>('accountFiles', []);
if (accountFiles.length === 0) {
accountFiles.push(defaultAccountsFile);
}
accountFiles.forEach(file => {
this.loadAccountFile(this.resolveFilePath(file)).then(accounts => {
this.accounts.push(...accounts);
});
});
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Race condition: accounts may not be loaded when completion is requested.

The constructor initiates async file loading but doesn't await completion. If provideCompletionItems is called before loading finishes, the user will see no completions.

Also, the non-null assertion on line 7 (!) will throw if the extension ID doesn't match exactly (e.g., during development with a different publisher).

🔎 Proposed fix using lazy loading
 export class LedgerAccountCompletion implements vscode.CompletionItemProvider {
-  accounts: string[] = [];
+  private accounts: string[] = [];
+  private accountsLoaded: Promise<void>;

   constructor() {
-    const defaultAccountsFile = vscode.Uri.joinPath(vscode.extensions.getExtension('parsa2820.ledger-cli')!.extensionUri, 'examples', 'accounts.ledger').fsPath;
+    const extension = vscode.extensions.getExtension('parsa2820.ledger-cli');
+    const defaultAccountsFile = extension 
+      ? vscode.Uri.joinPath(extension.extensionUri, 'examples', 'accounts.ledger').fsPath
+      : '';
     const accountFiles = vscode.workspace.getConfiguration('ledger').get<string[]>('accountFiles', []);
-    if (accountFiles.length === 0) {
+    if (accountFiles.length === 0 && defaultAccountsFile) {
       accountFiles.push(defaultAccountsFile);
     }
-    accountFiles.forEach(file => {
-      this.loadAccountFile(this.resolveFilePath(file)).then(accounts => {
-        this.accounts.push(...accounts);
-      });
-    });
+    this.accountsLoaded = this.loadAllAccounts(accountFiles);
   }

+  private async loadAllAccounts(accountFiles: string[]): Promise<void> {
+    const results = await Promise.all(
+      accountFiles.map(file => this.loadAccountFile(this.resolveFilePath(file)))
+    );
+    this.accounts = results.flat();
+  }

-  provideCompletionItems(...): ... {
+  async provideCompletionItems(...): Promise<vscode.CompletionItem[]> {
+    await this.accountsLoaded;
     return this.accounts.map(account => new vscode.CompletionItem(account, vscode.CompletionItemKind.Variable));
   }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/completion.ts around lines 6–17, the constructor starts async loading of
account files without awaiting (race condition) and uses a non-null assertion on
getExtension which can throw; create an ensureAccountsLoaded() method that
returns/sets a single Promise which loads account files once (store it as a
private accountsLoaded: Promise<void> | null), remove async work from the
constructor except to kick off but do not rely on completion there, and then
await await this.ensureAccountsLoaded() at the start of provideCompletionItems
to guarantee accounts are ready before computing completions; replace the
non-null assertion getExtension('parsa2820.ledger-cli')! with a safe check like
const ext = vscode.extensions.getExtension('parsa2820.ledger-cli'); if
ext?.extensionUri exists use it to build defaultAccountsFile, otherwise skip
adding the default or use a safe fallback, and ensure loadAccountFile results
are awaited/propagated into the accounts array inside the single accountsLoaded
promise.

Comment on lines +23 to +25
resolveCompletionItem?(item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem> {
throw new Error('Method not implemented.');
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove or properly implement resolveCompletionItem.

This method is optional in the CompletionItemProvider interface. Throwing an error will break completion resolution if VS Code calls it. Either remove it entirely or return the item unchanged.

🔎 Proposed fix
-  resolveCompletionItem?(item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem> {
-    throw new Error('Method not implemented.');
-  }
+  resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem> {
+    return item;
+  }

Or simply remove the method entirely since it's optional.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
resolveCompletionItem?(item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem> {
throw new Error('Method not implemented.');
}
resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem> {
return item;
}
🤖 Prompt for AI Agents
In src/completion.ts around lines 23 to 25, the optional resolveCompletionItem
method currently throws an Error which can break completion resolution; remove
this method entirely or change it to return the incoming item (e.g., return
item;) so it no longer throws — ensure the signature remains the same if kept
and return a vscode.ProviderResult<vscode.CompletionItem> with the unchanged
item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant