Skip to content

ianindratama/code-diffchecker-extension

Repository files navigation

Code Diff-Checker โ€” VS Code Extension

VS Code TypeScript License Tests

A VS Code extension that lets students compare their local project against a final solution hosted on GitHub, using a native TreeView UI with file-by-file diffs.

Built for Dicoding Academy โ€” an EdTech platform where students learn by building real projects.


โœจ Features

๐Ÿ”„ Automated Solution Fetching

The extension auto-activates when a project contains a .vscode/course-project.json config file. It reads the GitHub URL, branch, and target folder to fetch only the relevant solution files.

๐Ÿ“ Git Sparse-Checkout

Uses sparse-checkout to download only the specific folder needed for the current project โ€” saving bandwidth and time by ignoring the rest of the monorepo.

๐ŸŒณ Sidebar TreeView

A custom panel that visually lists all differing files, grouped by category (Added, Modified, Deleted) with themed icons. Clicking a file opens VS Code's native side-by-side diff editor.

๐Ÿ“ Dual Comparison Modes

  • Full Project Diff โ€” Compare the entire local project against the solution tree
  • Single File Diff โ€” Compare just the currently open file via right-click context menu or the editor title bar icon

๐Ÿ”ด Real-Time File Watching

When the student saves, creates, or deletes a file, the TreeView automatically updates within 300ms (debounced for performance).

๐Ÿ”” Background Update Notifications

Silently checks for solution updates in the background. If a newer version is available, a toast notification prompts the student to update.

๐Ÿ›ก๏ธ Smart Edge-Case Handling

  • Cross-platform line endings โ€” Normalizes CRLF/LF before comparison
  • Binary file detection โ€” Scans first 8KB for null bytes; binary files are flagged and prevented from opening in the text diff editor
  • Graceful Git process management โ€” Cross-platform process cleanup (Windows taskkill / POSIX signals) with timeouts
  • Failed pulls auto-recover โ€” Nukes broken cache and re-clones from scratch

Pedagogical design: There is intentionally no "Apply Changes" button. Students must manually read the diff and copy code โ€” this encourages deeper learning.


๐Ÿ“‹ Prerequisites

  • VS Code โ‰ฅ 1.85.0
  • Git โ‰ฅ 2.28 (required for --filter=blob:none sparse-checkout)
  • Node.js โ‰ฅ 18 (for development only)

๐Ÿš€ Getting Started

For Students (Using the Extension)

  1. Install the extension from the VS Code Marketplace (or install the .vsix file manually)
  2. Open a project that contains a .vscode/course-project.json file
  3. The extension activates automatically โ€” look for the Code Diff-Checker panel in the sidebar
  4. Run "Fetch Solution" from the Command Palette (Ctrl+Shift+P โ†’ Code Diff-Checker: Fetch Solution) or click the download icon in the TreeView header
  5. Click on any file in the TreeView to see the diff

Configuration File

Create a .vscode/course-project.json file in your project root:

{
  "repoUrl": "https://github.com/dicodingacademy/a159-flutter-pemula-labs.git",
  "branch": "main",
  "targetFolder": "navigation_project",
  "ignorePaths": ["build/", "*.iml"]
}
Field Required Description
repoUrl โœ… GitHub HTTPS clone URL
branch โœ… Branch containing the solution
targetFolder โœ… Folder path within the repo to compare against
ignorePaths โŒ Glob patterns for files to exclude from comparison (defaults to [])

๐ŸŽฎ Available Commands

Command Description Access
Fetch Solution Clone/update the solution and compute diff Command Palette, TreeView header, Status Bar
Compare Current File Diff the active editor file against the solution Right-click context menu, Editor title bar
Refresh Diff Re-compute diff from existing cache (no network) TreeView header
Clear Cache Delete the cached solution and reset the TreeView TreeView header menu

๐Ÿ—๏ธ Architecture

src/
โ”œโ”€โ”€ extension.ts          # Entry point โ€” registers commands, orchestrates modules
โ”œโ”€โ”€ types.ts              # Shared TypeScript interfaces
โ”œโ”€โ”€ constants.ts          # Timeouts, ignore patterns, min Git version
โ”œโ”€โ”€ config.ts             # Parses & validates .vscode/course-project.json
โ”œโ”€โ”€ processManager.ts     # Cross-platform child_process wrapper with timeout
โ”œโ”€โ”€ gitService.ts         # Git operations (clone, fetch, pull, version check)
โ”œโ”€โ”€ cacheManager.ts       # Cache lifecycle (MD5-hashed directories)
โ”œโ”€โ”€ diffEngine.ts         # Walks both trees, classifies added/modified/deleted
โ”œโ”€โ”€ treeViewProvider.ts   # Sidebar TreeView UI with themed icons
โ””โ”€โ”€ test/
    โ”œโ”€โ”€ config.test.ts       # 9 tests โ€” config validation
    โ”œโ”€โ”€ gitService.test.ts   # 9 tests โ€” Git version validation
    โ”œโ”€โ”€ diffEngine.test.ts   # 9 tests โ€” diff classification, binary detection
    โ””โ”€โ”€ __mocks__/vscode.js  # Minimal vscode API mock

Module Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  config.ts   โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ gitService.tsโ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚ cacheManager.tsโ”‚
โ”‚  (load JSON) โ”‚     โ”‚ (sparse clone)โ”‚     โ”‚  (MD5 cache)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
                            โ–ผ
                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                   โ”‚ diffEngine.ts  โ”‚โ”€โ”€โ”€โ”€โ–ถโ”‚treeViewProvider.tsโ”‚
                   โ”‚ (walk & diff)  โ”‚     โ”‚   (sidebar UI)    โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key Design Decisions

Decision Rationale
Git โ‰ฅ 2.28 required --filter=blob:none has bugs in 2.25โ€“2.27
taskkill /pid /T /F on Windows process.kill() sends POSIX signals that crash the Extension Host
Cache uses MD5 hash of config Ensures per-project isolation in globalStorageUri
Only .vscode/course-project.json is ignored The rest of .vscode/ (like launch.json) can be diffed
Binary detection via null-byte scan First 8KB checked โ€” prevents VS Code from rendering binary garbage
Failed pulls auto-nuke cache Guarantees a clean state on next attempt

๐Ÿ› ๏ธ Development

Setup

git clone https://github.com/ianindratama/code-diffchecker-extension.git
cd code-diffchecker
npm install

Build & Run

# Compile (single build via esbuild)
npm run compile

# Watch mode (auto-rebuild on changes)
npm run watch

# Run unit tests
node run-tests.js

# Lint
npm run lint

Debug

  1. Open this project in VS Code
  2. Press F5 to launch the Extension Development Host
  3. In the new window, open a project with a .vscode/course-project.json file
  4. Test the extension commands and TreeView

Package for Distribution

npx @vscode/vsce package

This generates a .vsix file that can be installed manually or published to the VS Code Marketplace.


โœ… Tests

27 unit tests across three modules โ€” all passing.

Module Tests What's Covered
Config Loader 9 Valid config, missing fields, invalid URL, malformed JSON
Git Service 9 Version validation (2.28+ required, Windows format, edge cases)
Diff Engine 9 Add/modify/delete classification, ignore layers, binary detection, CRLF normalization
# Run all tests
node run-tests.js

๐Ÿ“‚ Project Structure

code-diffchecker-extension/
โ”œโ”€โ”€ .vscode/
โ”‚   โ”œโ”€โ”€ launch.json          # F5 debug config
โ”‚   โ””โ”€โ”€ tasks.json           # Watch build task
โ”œโ”€โ”€ src/                     # TypeScript source
โ”‚   โ”œโ”€โ”€ test/                # Unit tests + mocks
โ”‚   โ””โ”€โ”€ *.ts                 # Core modules (see Architecture)
โ”œโ”€โ”€ out/                     # Compiled output (gitignored)
โ”œโ”€โ”€ package.json             # Extension manifest
โ”œโ”€โ”€ tsconfig.json            # TypeScript config (strict mode)
โ”œโ”€โ”€ esbuild.js               # Build script
โ”œโ”€โ”€ run-tests.js             # Test runner
โ”œโ”€โ”€ .eslintrc.json           # Linting rules
โ””โ”€โ”€ .vscodeignore            # Packaging exclusions

๐Ÿค Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add some feature')
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

Please ensure:

  • All existing tests pass (node run-tests.js)
  • TypeScript compiles with zero errors (npm run compile)
  • Code follows the existing ESLint rules (npm run lint)

๐Ÿ“„ License

This project is licensed under the MIT License โ€” see the LICENSE file for details.


๐Ÿ™ Acknowledgments

Built for Dicoding Academy to help students learn by comparing their work against reference solutions in a guided, educational workflow.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors