diff --git a/CHANGELOG.md b/CHANGELOG.md index 106b524..11c3aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,4 +6,10 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [Unreleased] -- Initial release \ No newline at end of file +- Added comprehensive docs set: + - `docs/ARCHITECTURE.md` (module/class audit, design rationale, integration gaps) + - `docs/USAGE.md` (installation, view opening modes, controls, workflow) +- Updated `README.md` with: + - feature status matrix + - development/test workflow + - known limitations and contribution notes diff --git a/README.md b/README.md index 894c21e..f20498c 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,83 @@ -# CODESCAPE +# Codescape -> Welcome to Codescapes, where you build cities from your code. This opensource project was built by members of Northeastern University's premier ideation club, *Forge* +Codescape is a VS Code extension that parses Java code and renders it as an isometric city. -## Highlights +- Buildings represent classes/interfaces. +- Height is based on methods + fields. +- The view updates from file watcher events via partial-state messages. -Codescapes will be baked into your repository as an extension of VSCode. This extension is intended for use with +## Current Status -Features: +Active prototype with working parser, watcher, relationship graph, and canvas renderer. -- Interactive cities of your code -- Buildings created by the functionality of your code and methods -- Exportable cities in HTML/React +## Feature Status -## Overview +| Area | Status | Notes | +|---|---|---| +| Java parsing (Tree-sitter) | Implemented | Classes/interfaces, methods, fields, constructors | +| Relationship graph | Implemented | Extends/implements/field/ctor dependencies | +| Incremental updates | Implemented | Watcher emits `PARTIAL_STATE` | +| Explorer webview | Implemented | `codescape.Cityview` | +| Panel webview | Implemented | Open via `codescape.createPanel` | +| Auto-layout abstraction (`src/layout/placer.ts`) | Partial | Exists/tests pass, not wired into live renderer | +| Message contract typing (`src/types/messages.ts`) | Partial | Does not fully match runtime payloads | +| Pan/rotation controls | Not implemented | Zoom-only camera controls | -This repository is still a WIP. Hang tight as we begin implementing code! +## Documentation -### Development Stage +- [Usage Guide](docs/USAGE.md) +- [Architecture Reference](docs/ARCHITECTURE.md) -This project is brand new. It has no supporting code implementations, nor a stable release. +## Quick Start -### Authors +1. Install dependencies: +```bash +npm install +``` +2. Compile: +```bash +npm run compile +``` +3. Launch extension host (`F5` in VS Code). +4. In the extension host window: + - Open the explorer view `Codescape City`, or + - Run command `Create Panel` (`codescape.createPanel`). -I'm Peter SantaLucia (https://github.com/pdsl2005), the project manager and the maintainer of this repository. +## Development -### License +- Watch compile: +```bash +npm run watch +``` +- Lint: +```bash +npm run lint +``` +- Tests: +```bash +npm test +``` -This is free software: you can redistribute or modify the code based on the terms of the **GNU GPL-3.0** License. A copy of this license is provided in [LICENSE](https://github.com/pdsl2005/codescape/blob/main/LICENSE) +Test notes: +- `npm test` runs compile + lint + VS Code extension tests. +- In offline/restricted environments, `vscode-test` may be flaky depending on local VS Code test host availability. + +## Commands + +Contributed commands: +- `codescape.createPanel` (`Create Panel`) +- `codescape.scan` (`Codescape Scan`) + +Runtime-registered internal commands: +- `codescape.dumpParseStore` +- `codescape.exportParseStore` + +## Contributing + +1. Keep runtime message contracts synchronized between extension/watcher/frontend/types. +2. Prefer small, test-backed PRs (parser, relations, watcher, and layout have existing test suites). +3. Update [Usage Guide](docs/USAGE.md) and [Architecture Reference](docs/ARCHITECTURE.md) when behavior changes. + +## License + +GNU GPL-3.0. See [LICENSE](LICENSE). diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..b82b384 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,294 @@ +# Codescape Architecture Reference + +## 1) Current System Overview +Codescape is a VS Code extension that parses Java files with Tree-sitter and renders classes as an isometric city in webviews. + +- Backend parses `.java` files into `ClassInfo[]`. +- In-memory store tracks parse state per file. +- File watcher emits incremental frontend updates (`PARTIAL_STATE`). +- Frontend canvas renders buildings from class metadata. + +High-level flow: + +```text +Java files -> parser/javaExtractor -> parser -> FileParseStore + | + +-> on activation scan + +-> on file change/delete + | + v + JavaFileWatcher -> PARTIAL_STATE -> webview script -> render +``` + +## 2) Module and Class Audit + +This section covers all current modules under `src/` and `media/`. + +### Extension Layer + +#### `src/extension.ts` + +- `activate(context: vscode.ExtensionContext)` + - Purpose: extension bootstrap/orchestration. + - Responsibilities: + - Creates `FileParseStore` and `JavaFileWatcher`. + - Initializes parser via `initializeParser()`. + - Registers commands: + - `codescape.scan` + - `codescape.createPanel` + - `codescape.dumpParseStore` + - `codescape.exportParseStore` + - Registers explorer webview provider: `codescape.Cityview`. + - Performs startup parse of workspace Java files. + - Interactions: + - Calls `parseAndStore()` for initial population. + - Passes webviews to watcher for incremental updates. + +- `createPanel(context, javaWatcher)` + - Purpose: opens editor-tab webview panel (`Codescape`). + - Interactions: + - Injects HTML from `getWebviewContent()`. + - Adds panel webview to `JavaFileWatcher`. + - Posts a legacy `AST_DATA` payload (placeholder/bootstrap behavior). + +- `workspaceScan(store)` + - Purpose: manual command-triggered parse pass. + - Interactions: + - Uses `getJavaFiles()` + `parseAndStore()`. + +- `getJavaFiles()` + - Purpose: find all Java files, honoring `.exclude` glob entries. + +- `isExcluded(uri)` + - Purpose: check if file path matches `.exclude` patterns. + - Abstraction: delegates matching to `minimatch`. + +- `CodescapeViewProvider implements vscode.WebviewViewProvider` + - Purpose: explorer/sidebar view provider (`codescape.Cityview`). + - Interaction: registers webview with `JavaFileWatcher` for shared updates. + +- `getWebviewContent(webview, extensionUri)` + - Purpose: returns full frontend HTML+script. + - Frontend state model inside script: + - `state.classes`: `ClassInfo[]` + - `state.layout`: class -> grid position + - `state.colors`: class -> assigned color + - `state.status`: `loading | ready | empty | error` + +### Watcher and Incremental Update Layer + +#### `src/JavaFileWatcher.ts` + +- `type IncrementalChangePayload` + - `{ changed?: ClassInfo[]; related?: ClassInfo[]; removed?: string[] }`. + +- `class JavaFileWatcher` + - Purpose: watches `**/*.java` and pushes incremental updates to active webviews. + - Core fields: + - `_watcher: vscode.FileSystemWatcher` + - `_webviews: vscode.Webview[]` + - Methods: + - `addWebview(view)`: subscribes webview. + - `removeWebview(view)`: unsubscribes webview. + - `handleIncrementalChange(uri, store)`: parse changed file, compute related classes, broadcast `PARTIAL_STATE`. + - `buildPartialStatePayload(changed, removed, store)`: relationship-aware payload builder. + - `postIncrementalChange(payload, views)`: sends `PARTIAL_STATE`. + - `dispose()`: dispose file watcher. + - Interactions: + - Uses `parseAndStore()` from parser. + - Uses `buildGraph()/getRelated()` from relations. + - Uses `isExcluded()` from extension. + +### Parsing Layer + +#### `src/parser.ts` + +- `ensureInitialized()` / `initializeParser()` + - Purpose: idempotent parser init. + +- `parseJavaFile(uri)` + - Purpose: read Java file and extract classes. + +- `parseAndStore(uri, store)` + - Purpose: orchestrates parse lifecycle. + - Steps: + - mark pending + - parse with Tree-sitter + - set parsed result + - export sidecar JSON (`*.json` next to source) + - return `{ changed, removed }` + +- `getData(uri, store)` + - Purpose: store accessor. + +#### `src/parser/javaExtractor.ts` + +- Purpose: Tree-sitter Java extraction logic. +- Key interfaces: + - `ClassInfo` + - `MethodInfo` + - `FieldInfo` + - `ConstructorInfo` + - `ParameterInfo` +- Key functions: + - `initParser()` + - `extractClasses(source)` + - helper extraction functions for methods, fields, constructors, types, modifiers, inheritance. +- Notable behavior: + - Handles classes and interfaces (including nested declarations). + - Type extraction normalizes many forms (primitive, array, generic base type, scoped identifiers). + +### State and Relation Layer + +#### `src/state.ts` + +- `interface StoreEntry` + - `{ status: 'pending' | 'parsed'; data?: ClassInfo[] }` + +- `class FileParseStore` + - Purpose: typed in-memory parse-state map keyed by URI string. + - Methods: `markPending`, `setParsed`, `remove`, `get`, `snapshot`. + +#### `src/relations.ts` + +- `interface ClassGraph` + - `dependsOn` and `dependedOnBy` adjacency maps. + +- `buildGraph(allClasses)` + - Purpose: build dependency graph from inheritance/implements/fields/ctor params. + +- `getRelated(changedNames, graph)` + - Purpose: find classes dependent on changed/removed classes. + +### Frontend Rendering Layer + +#### `src/webview/renderer.js` + +- Purpose: canvas isometric primitives. +- Functions: + - `drawIsoGrid` + - `shade` + - `drawIsoCube` + - `drawIsoBuilding` + - `placeIsoBuilding` + +#### `src/webview/uml.js` + +- Purpose: draw UML class box on canvas. +- Function: + - `drawUmlBox` + +#### Inline frontend runtime (`getWebviewContent` in `extension.ts`) + +- Purpose: state machine + render loop + message handling. +- Handles messages: + - `FULL_STATE` (legacy path, references `fileData`) + - `AST_DATA` (legacy/mock path) + - `PARTIAL_STATE` (active incremental path) +- Current incremental behavior: + - Calls `updateState(changed)` then `updateState(related)` if present. + - This currently replaces full state with subsets instead of merging. + +### Layout Subsystem + +#### `src/layout/types.ts` + +- `BuildingNode`, `BuildingPosition`, `LayoutMap`. + +#### `src/layout/placer.ts` + +- `computeLayout(nodes)` + - Purpose: relationship-grouped row layout algorithm. + - Status: tested, but not wired into active webview layout path. + +#### `src/layout/demo.ts` + +- Purpose: local/demo harness for trying `computeLayout()` with sample nodes. +- Status: developer utility; not imported by runtime extension code. + +### Message Contract Types + +#### `src/types/messages.ts` + +- Defines `FullStateMessage`, `PartialStateMessage`, `ReadyMessage`, etc. +- Status: partially out of sync with runtime payload shapes. + +### Legacy/Prototype Frontend Modules + +#### `media/index.html`, `media/main.js`, `media/renderer.js` + +- Purpose: earlier standalone renderer/prototype assets. +- Status: not used by the active extension webview (`getWebviewContent` + `src/webview/*`). +- Interaction: none in current runtime path. + +### Tests + +- `src/test/parser.test.ts`: parser coverage with fixtures. +- `src/test/relations.test.ts`: graph and related-class behavior. +- `src/test/layout.test.ts`: layout algorithm behavior. +- `src/test/watcher.test.ts`: store lifecycle test (currently contains an assertion mismatch in expected parsed data shape). +- `src/test/extension.test.ts`: placeholder sample test. + +## 3) Design Decisions and Rationale + +### Canvas over Three.js +Rationale: +- Isometric rendering needs 2.5D projection, not a full 3D scene graph. +- Lower dependency and runtime complexity in VS Code webview sandbox. +- Smaller bundle and easier control over pixel-level rendering. + +### Frontend-Owned Auto Layout +Rationale: +- Layout is primarily presentation logic. +- Keeps backend focused on semantic model (`ClassInfo`). +- Avoids backend round-trip for every visual recalculation. + +Current status: +- Active layout is inline (`runAutoLayout` in webview script). +- `src/layout/placer.ts` exists as an abstraction candidate, not yet integrated. + +### Full-State vs Partial-State Split +Intended rationale: +- Full snapshot once at load. +- Incremental payloads on change/delete for performance and responsiveness. + +Current code state: +- Watcher emits `PARTIAL_STATE`. +- Startup panel currently posts legacy `AST_DATA` mock data. +- Message contract has legacy branches (`FULL_STATE`, `AST_DATA`, `READY`) and needs consolidation. +- This split remains the correct architecture even though implementation still has legacy paths. + +### Multi-View Architecture +Rationale: +- Support both explorer view and independent editor panel. +- Shared rendering stack allows consistent experience across placements. + +Current implementation: +- Explorer view provider is registered. +- Separate `codescape.createPanel` command opens panel view. +- Watcher broadcasts updates to all registered webviews. + +### Persistence Approach +Current approach: +- Primary state: in-memory `FileParseStore`. +- Artifact persistence: per-file JSON sidecars from `parseAndStore`. +- Export utility: workspace-level `codescape-output.json` command. + +Rationale: +- Fast startup and simple runtime model. +- JSON outputs provide inspectable parse artifacts without database complexity. + +## 4) Current Gaps and Behavioral Notes + +- `codescape.scan` reparses store data but does not currently broadcast a full-state refresh to already-open webviews. +- `PARTIAL_STATE` frontend handling currently applies subset updates (`changed`, then `related`) instead of merging against a canonical full state model. +- Relationship data is computed backend-side, but frontend color mapping is still class-stable palette assignment (not relationship-based encoding yet). +- `src/types/messages.ts` should be aligned with live runtime payloads. + +## 5) How Everything Fits Together + +- Parsing and dependency graphing live in backend TypeScript modules. +- Watcher transforms file events into semantic incremental payloads. +- Webviews consume payloads and own visual state + rendering. +- Two display surfaces (explorer webview and panel webview) can receive the same updates. +- The system is structurally modular, but message-contract consolidation is the next key step for reliability. diff --git a/docs/USAGE.md b/docs/USAGE.md new file mode 100644 index 0000000..d8093f7 --- /dev/null +++ b/docs/USAGE.md @@ -0,0 +1,111 @@ +# Codescape User Guide + +## 1) Installation + +### Prerequisites +- VS Code `^1.74.0` +- Node.js + npm +- Java project/workspace with `.java` files + +### Build and run from source +1. Clone and enter repo. +2. Install dependencies: + ```bash + npm install + ``` +3. Compile: + ```bash + npm run compile + ``` +4. Launch extension host from VS Code with `F5`. + +## 2) Opening the City View + +Codescape currently supports two user-visible locations: + +1. Explorer sidebar view: +- In VS Code explorer, open **Codescape City** (`codescape.Cityview`). + +2. Editor panel view: +- Run command **Create Panel** (`codescape.createPanel`) from command palette. +- This opens a tab titled `Codescape`. + +Placement options in VS Code: +- Tab: default open behavior. +- Split pane: drag tab or use split editor command. +- Bottom panel: with Codescape tab focused, run **View: Move Editor into Panel**. + +## 3) What the Visualization Means + +- Building = Java class/interface (`ClassInfo`). +- Building height = complexity proxy (`methods + fields`, min 1). +- Building color = relationship signal (intended UX) and currently implemented as stable per-class palette assignment. +- Related classes = computed in backend (`relations.ts`) for incremental updates. + +Important current behavior: +- Related classes are computed and sent in `PARTIAL_STATE`. +- UI currently logs related classes and updates state subsets; dedicated relationship color/highlight encoding is not finalized. + +## 4) Controls + +- Zoom in: mouse wheel up. +- Zoom out: mouse wheel down. +- Zoom range: `0.3` to `3.0`. +- Pan: not implemented. +- Rotation: not implemented. + +## 5) Incremental Updates + +Codescape watches `**/*.java` and sends partial updates: + +- File changed: + - Re-parse file. + - Compute `changed`, `removed`, `related`. + - Broadcast `PARTIAL_STATE` to active webviews. + +- File deleted: + - Remove from store. + - Broadcast `PARTIAL_STATE` with `removed` class names. + +## 6) Excluding Files + +Create `.exclude` in workspace root. +Each line is a glob pattern matched with `minimatch`. + +Example: +```text +**/generated/** +**/build/** +**/test/** +``` + +## 7) Commands + +Contributed commands (`package.json`): +- `codescape.createPanel` -> **Create Panel** +- `codescape.scan` -> **Codescape Scan** + +Runtime-registered internal commands (not contributed in `package.json`): +- `codescape.dumpParseStore` +- `codescape.exportParseStore` + +## 8) Practical Workflow + +1. Start extension host (`F5`). +2. Open Java workspace in extension host window. +3. Open Codescape via sidebar or `Create Panel` command. +4. Edit/save Java files and observe updates. +5. Use zoom wheel to inspect layout. + +## 9) Troubleshooting + +- City view not updating: + - Confirm `.java` file is not excluded by `.exclude`. + - Check extension host logs for parser errors. + +- Empty view: + - Verify workspace has Java files. + - Run `codescape.scan` (re-parses backend store; current implementation may still require reopening/reloading view to reflect a full-state refresh). + +- Commands missing: + - Recompile (`npm run compile`) and relaunch extension host.