diff --git a/docs/FRICTIONLESS_SETUP_PLAN.md b/docs/FRICTIONLESS_SETUP_PLAN.md deleted file mode 100644 index 8b1378917..000000000 --- a/docs/FRICTIONLESS_SETUP_PLAN.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docs/JS_PROMPT_PARITY_RECOMMENDATIONS.md b/docs/JS_PROMPT_PARITY_RECOMMENDATIONS.md deleted file mode 100644 index 8b1378917..000000000 --- a/docs/JS_PROMPT_PARITY_RECOMMENDATIONS.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/docs/claude-code-plugin/getting-started.mdx b/docs/claude-code-plugin/getting-started.mdx new file mode 100644 index 000000000..a951939b8 --- /dev/null +++ b/docs/claude-code-plugin/getting-started.mdx @@ -0,0 +1,95 @@ +--- +title: "Getting Started" +description: "Install the Codeflash Claude Code plugin and run your first optimization" +icon: "rocket" +sidebarTitle: "Getting Started" +--- + +This guide walks you through installing the Codeflash Claude Code plugin and running your first optimization. + +## Prerequisites + +- **Claude Code** v2.1.38 or later +- **Python projects**: [codeflash](https://pypi.org/project/codeflash/) installed in a virtual environment +- **JS/TS projects**: [codeflash](https://www.npmjs.com/package/codeflash) installed as a dev dependency + +## Installation + +### Add the marketplace and install + +```bash +/plugin marketplace add codeflash-ai/codeflash-cc-plugin +/plugin install codeflash +``` + +Or from a local clone: + +```bash +git clone https://github.com/codeflash-ai/codeflash-cc-plugin.git +/plugin marketplace add ./codeflash-cc-plugin +/plugin install codeflash +``` + +### Choose installation scope + +By default, plugins install at the **user** level (available across all projects). You can change this: + +| Scope | Flag | Effect | +|-------|------|--------| +| User (default) | _(none)_ | Available in all your projects | +| Project | `--scope project` | Shared with team via `.claude/settings.json` | +| Local | `--scope local` | This project only, gitignored | + +```bash +/plugin install codeflash --scope project +``` + +### Verify installation + +Run `/plugin` to open the plugin manager. Confirm **codeflash** appears under the **Installed** tab. + +## First optimization + +Run the `/optimize` skill with a target file: + +``` +/optimize src/utils.py +``` + +What happens behind the scenes: + +1. The skill forks a background **optimizer agent** +2. The agent walks upward from CWD to the git root, looking for `pyproject.toml` (Python) or `package.json` (JS/TS) +3. It verifies codeflash is installed and configured +4. If configuration is missing, it auto-discovers your module root and tests directory and writes the config for you +5. It runs `codeflash --subagent` in the background with a 10-minute timeout +6. Results are reported when optimization completes + +You can continue working while codeflash optimizes in the background. + +## Set up auto-permissions + +Run `/codeflash:setup` to allow codeflash to execute automatically without permission prompts: + +``` +/codeflash:setup +``` + +This adds `Bash(*codeflash*)` to the `permissions.allow` array in `.claude/settings.json`. After this, the post-commit hook can trigger optimizations without asking each time. + +## Next steps + + + + All commands, flags, and workflows + + + Config reference for Python and JS/TS projects + + + Common problems and fixes + + + How the plugin works internally + + diff --git a/docs/claude-code-plugin/troubleshooting.mdx b/docs/claude-code-plugin/troubleshooting.mdx new file mode 100644 index 000000000..911d795de --- /dev/null +++ b/docs/claude-code-plugin/troubleshooting.mdx @@ -0,0 +1,114 @@ +--- +title: "Troubleshooting" +description: "Common problems and fixes for the Codeflash Claude Code plugin" +icon: "wrench" +sidebarTitle: "Troubleshooting" +--- + +## Plugin not appearing after install + +**Symptom**: `/plugin` doesn't show codeflash in the Installed tab. + +**Fix**: +1. Verify the marketplace was added: `/plugin marketplace add codeflash-ai/codeflash-cc-plugin` +2. Install again: `/plugin install codeflash` +3. Check you're running Claude Code v2.1.38 or later + +## `/optimize` does nothing + +**Symptom**: Running `/optimize` produces no output or immediately returns. + +**Possible causes**: +- No project config found. The agent walks from CWD to the git root looking for `pyproject.toml` or `package.json`. Make sure you're inside a git repository. +- Codeflash CLI not installed. For Python: `pip install codeflash` in your venv. For JS/TS: `npm install --save-dev codeflash`. +- The agent is running in the background. Check if you see "Codeflash is optimizing in the background" — results appear when the background task completes. + +## Permission prompts every time + +**Symptom**: Claude asks for permission to run codeflash on every invocation. + +**Fix**: Run `/setup` to add `Bash(*codeflash*)` to `.claude/settings.json`. Or add it manually: + +```json +{ + "permissions": { + "allow": [ + "Bash(*codeflash*)" + ] + } +} +``` + +## No venv found (Python) + +**Symptom**: Hook or agent reports "No Python virtual environment was found." + +**Fix**: +1. Create a venv: `python3 -m venv .venv` +2. Activate it: `source .venv/bin/activate` +3. Install codeflash: `pip install codeflash` +4. Restart Claude Code from within the activated venv + +The plugin searches for venvs in this order: +1. `/.venv` +2. `/venv` +3. `/.venv` +4. `/venv` + +## Codeflash not installed (JS/TS) + +**Symptom**: `npx codeflash --version` fails or package not found. + +**Fix**: + +```bash +npm install --save-dev codeflash +``` + +Run this in the directory containing your `package.json`. + +## Hook not triggering after commits + +**Symptom**: You commit Python/JS/TS files but don't see optimization suggestions. + +**Check**: +1. Verify the hook is registered: look for `hooks/hooks.json` in the plugin directory +2. Check the debug log: `cat /tmp/codeflash-hook-debug.log` +3. Ensure commits touch `.py`, `.js`, `.ts`, `.jsx`, or `.tsx` files +4. The hook only detects commits made **during the current session** (after the transcript file was created). Commits from before starting Claude Code won't trigger it. + +## Hook triggering repeatedly + +**Symptom**: The hook keeps suggesting optimization for the same commits. + +This shouldn't happen due to deduplication (the hook tracks seen commit hashes in `$TRANSCRIPT_DIR/codeflash-seen`). If it does: + +1. Check the seen-marker file exists in the transcript directory +2. Look at `/tmp/codeflash-hook-debug.log` for the dedup logic trace +3. If commit hashes changed (e.g., amended commits), the hook treats them as new + +## "Attempting to repair broken tests..." + + +This is **normal codeflash behavior**, not an error. Codeflash generates tests and sometimes needs to fix them. Let it continue. + + +## 10-minute timeout exceeded + +**Symptom**: Codeflash background task times out. + +This can happen on large projects or with `--all`. Options: +- Optimize specific files instead of the entire project: `/optimize src/specific_file.py` +- Target individual functions: `/optimize src/utils.py my_function` +- The `--all` flag scans every function, which naturally takes longer + +## Formatter errors + +**Symptom**: Codeflash fails with formatter-related errors. + +**Check**: +1. Read the `formatter-cmds` (Python) or `formatterCmds` (JS/TS) in your config +2. Verify each formatter is installed: + - Python: `which black` (or whichever formatter) + - JS/TS: `npx prettier --version` (or whichever formatter) +3. Set `formatter-cmds = ["disabled"]` or `"formatterCmds": ["disabled"]` to skip formatting entirely diff --git a/docs/claude-code-plugin/usage-guide.mdx b/docs/claude-code-plugin/usage-guide.mdx new file mode 100644 index 000000000..12d5ba25d --- /dev/null +++ b/docs/claude-code-plugin/usage-guide.mdx @@ -0,0 +1,53 @@ +--- +title: "Usage Guide" +description: "Commands, flags, and workflows for the Codeflash Claude Code plugin" +icon: "book" +sidebarTitle: "Usage Guide" +--- + +## The `/optimize` skill + +`/optimize` is the primary command. It spawns a background optimizer agent that runs the codeflash CLI on your code. + +### Syntax + +``` +/optimize [file] [function] [flags] +``` + +### Examples + +| Command | Effect | +|---------|--------| +| `/optimize` | Let codeflash detect changed files automatically | +| `/optimize src/utils.py` | Optimize all functions in `src/utils.py` | +| `/optimize src/utils.py my_function` | Optimize only `my_function` in that file | +| `/optimize --all` | Optimize the entire project | + +Flags can be combined: `/optimize src/utils.py my_function` + +### What happens behind the scenes + +1. The skill (defined in `skills/optimize/SKILL.md`) forks context and spawns the **optimizer agent** +2. The agent locates your project config (`pyproject.toml` or `package.json` or `codeflash.toml`) +3. It verifies the codeflash CLI is installed and the project is configured +4. It runs `codeflash --subagent` as a **background task** with a 10-minute timeout +5. You're notified when optimization completes with results + +The agent has up to **15 turns** to complete its work (install codeflash, configure the project, run optimization). + +## The `/codeflash:setup` command + +`/codeflash:setup` configures auto-permissions so codeflash runs without prompting. + +### What it does + +1. Finds `.claude/settings.json` in your project root +2. Checks if `Bash(*codeflash*)` is already in `permissions.allow` +3. If not, adds it (creating the file and directory if needed) +4. Preserves any existing settings + + +Running `/codeflash:setup` multiple times is safe — it's idempotent. If permissions are already configured, it reports "No changes needed." + + diff --git a/docs/configuration.mdx b/docs/configuration.mdx deleted file mode 100644 index 29506b952..000000000 --- a/docs/configuration.mdx +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Manual Configuration" -description: "Configure Codeflash for your project" -icon: "gear" -sidebarTitle: "Manual Configuration" -keywords: - [ - "configuration", - "setup", - "settings", - ] ---- - -# Manual Configuration - -Codeflash is installed and configured on a per-project basis. -`codeflash init` should guide you through the configuration process, but if you need to manually configure Codeflash or set advanced settings, follow the guide for your language: - - - - Configure via `pyproject.toml` - - - Configure via `package.json` - - \ No newline at end of file diff --git a/docs/docs.json b/docs/docs.json index fe0c23098..8fc5ddde8 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -65,6 +65,14 @@ "editor-plugins/vscode/configuration", "editor-plugins/vscode/troubleshooting" ] + }, + { + "group": "Claude Code Plugin", + "pages": [ + "claude-code-plugin/getting-started", + "claude-code-plugin/usage-guide", + "claude-code-plugin/troubleshooting" + ] } ] } diff --git a/docs/install.md b/docs/install.md deleted file mode 100644 index f2afff145..000000000 --- a/docs/install.md +++ /dev/null @@ -1,167 +0,0 @@ -# Codeflash Installation Guide - -I need to install and configure Codeflash for my project to enable AI-powered performance optimization. - -## Objective - -Install Codeflash CLI and configure it for either Python or JavaScript/TypeScript project with proper test data serialization and GitHub integration. - -## Success Condition - -Codeflash is successfully installed, configured with API key, connected to GitHub, and can run optimization commands without errors. - -## TODO - -1. Install Codeflash CLI for your language -2. Run initialization and configuration -3. Generate and configure API key -4. Install GitHub App -5. Verify installation - -## Installation Steps - -### For Python Projects - -**Prerequisites:** -- Python 3.9 or above -- Virtual environment activated -- Project dependencies installed - -**Commands:** - -```bash -# Activate virtual environment -source venv/bin/activate # Linux/Mac -# or -venv\Scripts\activate # Windows - -# Install Codeflash -pip install codeflash - -# Or as dev dependency with modern tools -uv add --dev codeflash -# or -poetry add codeflash@latest --group dev - -# Initialize configuration -cd /path/to/project/root -codeflash init -``` - -**Configuration prompts:** -1. Enter Codeflash API key -2. Specify Python module to optimize (e.g., `my_module`) -3. Specify test location (e.g., `tests/`) -4. Select code formatter (black/ruff/other/disabled) -5. Select git remote for PRs -6. Opt-in to anonymous usage data -7. Install GitHub app -8. Install GitHub actions - -### For JavaScript/TypeScript Projects - -**Prerequisites:** -- Node.js 16 or above -- Package manager (npm/yarn/pnpm/bun) -- Project dependencies installed - -**Commands:** - -```bash -# Verify Node.js version -node --version # Should be v16.0.0+ - -# Install Codeflash as dev dependency -npm install --save-dev codeflash -# or -yarn add --dev codeflash -# or -pnpm add --save-dev codeflash -# or -bun add --dev codeflash - -# Or install globally -npm install -g codeflash - -# Initialize configuration -cd /path/to/project/root -codeflash init -``` - -**Configuration prompts:** -1. Enter Codeflash API key -2. Specify JavaScript/TypeScript module (e.g., `src/`) -3. Specify test location (e.g., `tests/`, `__tests__/`, `*.test.js`) -4. Select test framework (jest/vitest/mocha/ava/other) -5. Select code formatter (prettier/eslint/biome/disabled) -6. Select git remote for PRs -7. Opt-in to anonymous usage data -8. Install GitHub app -9. Install GitHub actions - -**Serialization Strategy:** -JavaScript/TypeScript projects use V8 serialization automatically for optimal test data capture: -- Binary storage format -- Perfect type preservation (Date, Map, Set, TypedArrays, BigInt, etc.) -- 2-3x faster than alternatives -- Framework agnostic (React, Vue, Angular, Svelte, etc.) - -### API Key Generation - -**Steps:** -1. Visit https://app.codeflash.ai/ -2. Sign up with GitHub account (free tier available) -3. Navigate to https://app.codeflash.ai/app/apikeys -4. Generate new API key -5. Copy and paste when prompted during `codeflash init` - -### GitHub App Installation - -**Steps:** -1. Visit https://github.com/apps/codeflash-ai/installations/select_target -2. Select the repository to install Codeflash -3. Grant necessary permissions -4. Confirm installation - -## Verification - -**Test the installation:** - -```bash -# Python - Optimize single function -codeflash --file path/to/file.py --function function_name - -# JavaScript/TypeScript - Optimize single function -codeflash --file path/to/file.js --function functionName - -# Optimize entire codebase (both languages) -codeflash --all - -# Verbose output for debugging -codeflash optimize --verbose -``` - -## Configuration Files - -**Python:** -- Configuration stored in `pyproject.toml` -- Serialization: SQLite + pickle - -**JavaScript/TypeScript:** -- Configuration stored in `codeflash.config.js` -- Serialization: V8 binary format - -## Framework Support - -**Python:** -- All Python projects with pytest, unittest, or similar - -**JavaScript/TypeScript:** -- Frontend: React, Vue, Angular, Svelte, Solid.js -- Backend: Express, NestJS, Fastify, Koa, Hono -- Testing: Jest, Vitest, Mocha, AVA, Playwright, Cypress -- Runtimes: Node.js (✅ Recommended), Bun/Deno (Coming soon) - -## Execute Installation - -Run the commands above for your specific language and answer the configuration prompts to complete Codeflash installation. \ No newline at end of file diff --git a/docs/java-support-architecture.md b/docs/java-support-architecture.md deleted file mode 100644 index 25ab0d003..000000000 --- a/docs/java-support-architecture.md +++ /dev/null @@ -1,1095 +0,0 @@ -# Java Language Support Architecture for CodeFlash - -## Executive Summary - -Adding Java support to CodeFlash requires implementing the `LanguageSupport` protocol with Java-specific components for parsing, test discovery, context extraction, and test execution. The existing architecture is well-designed for multi-language support, and Java can follow the established patterns from Python and JavaScript/TypeScript. - ---- - -## 1. Architecture Overview - -### Current Language Support Stack - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ Core Optimization Pipeline │ -│ (language-agnostic: optimizer.py, function_optimizer.py) │ -└───────────────────────────────┬─────────────────────────────────┘ - │ - ┌───────────▼───────────┐ - │ LanguageSupport │ - │ Protocol │ - └───────────┬───────────┘ - │ - ┌───────────────────────┼───────────────────────┐ - ▼ ▼ ▼ -┌───────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ PythonSupport │ │JavaScriptSupport│ │ JavaSupport │ -│ (mature) │ │ (functional) │ │ (NEW) │ -├───────────────┤ ├─────────────────┤ ├─────────────────┤ -│ - libcst │ │ - tree-sitter │ │ - tree-sitter │ -│ - pytest │ │ - jest │ │ - JUnit 5 │ -│ - Jedi │ │ - npm/yarn │ │ - Maven/Gradle │ -└───────────────┘ └─────────────────┘ └─────────────────┘ -``` - -### Proposed Java Module Structure - -``` -codeflash/languages/java/ -├── __init__.py # Module exports, register language -├── support.py # JavaSupport class (main implementation) -├── parser.py # Tree-sitter Java parsing utilities -├── discovery.py # Function/method discovery -├── context_extractor.py # Code context extraction -├── import_resolver.py # Java import/dependency resolution -├── instrument.py # Test instrumentation -├── test_runner.py # JUnit test execution -├── comparator.py # Test result comparison -├── build_tools.py # Maven/Gradle integration -├── formatter.py # Code formatting (google-java-format) -└── line_profiler.py # JProfiler/async-profiler integration -``` - ---- - -## 2. Core Components - -### 2.1 Language Registration - -```python -# codeflash/languages/java/support.py - -from codeflash.languages.base import Language, LanguageSupport -from codeflash.languages.registry import register_language - -@register_language -class JavaSupport: - @property - def language(self) -> Language: - return Language.JAVA # Add to Language enum - - @property - def file_extensions(self) -> tuple[str, ...]: - return (".java",) - - @property - def test_framework(self) -> str: - return "junit" - - @property - def comment_prefix(self) -> str: - return "//" -``` - -### 2.2 Language Enum Extension - -```python -# codeflash/languages/base.py - -class Language(Enum): - PYTHON = "python" - JAVASCRIPT = "javascript" - TYPESCRIPT = "typescript" - JAVA = "java" # NEW -``` - ---- - -## 3. Component Implementation Details - -### 3.1 Parsing (tree-sitter-java) - -**File: `codeflash/languages/java/parser.py`** - -Tree-sitter has excellent Java support. Key node types to handle: - -| Java Construct | Tree-sitter Node Type | -|----------------|----------------------| -| Class | `class_declaration` | -| Interface | `interface_declaration` | -| Method | `method_declaration` | -| Constructor | `constructor_declaration` | -| Static block | `static_initializer` | -| Lambda | `lambda_expression` | -| Anonymous class | `anonymous_class_body` | -| Annotation | `annotation` | -| Generic type | `type_parameters` | - -```python -class JavaParser: - """Tree-sitter based Java parser.""" - - def __init__(self): - self.parser = Parser() - self.parser.set_language(tree_sitter_java.language()) - - def find_methods(self, source: str) -> list[MethodNode]: - """Find all method declarations.""" - tree = self.parser.parse(source.encode()) - return self._walk_for_methods(tree.root_node) - - def find_classes(self, source: str) -> list[ClassNode]: - """Find all class/interface declarations.""" - ... - - def get_method_signature(self, node: Node) -> MethodSignature: - """Extract method signature including generics.""" - ... -``` - -### 3.2 Function Discovery - -**File: `codeflash/languages/java/discovery.py`** - -Java-specific considerations: -- Methods are always inside classes (no top-level functions) -- Need to handle: instance methods, static methods, constructors -- Interface default methods -- Annotation processing (`@Override`, `@Test`, etc.) -- Inner classes and nested methods - -```python -def discover_functions( - file_path: Path, - criteria: FunctionFilterCriteria | None = None -) -> list[FunctionInfo]: - """ - Discover optimizable methods in a Java file. - - Returns methods that are: - - Public or protected (can be tested) - - Not abstract - - Not native - - Not in test files - - Not trivial (getters/setters unless specifically requested) - """ - parser = JavaParser() - source = file_path.read_text(encoding="utf-8") - - methods = [] - for class_node in parser.find_classes(source): - for method in class_node.methods: - if _should_include_method(method, criteria): - methods.append(FunctionInfo( - name=method.name, - file_path=file_path, - start_line=method.start_line, - end_line=method.end_line, - parents=(ParentInfo( - name=class_node.name, - type="ClassDeclaration" - ),), - is_async=method.has_annotation("Async"), - is_method=True, - language=Language.JAVA, - )) - return methods -``` - -### 3.3 Code Context Extraction - -**File: `codeflash/languages/java/context_extractor.py`** - -Java context extraction must handle: -- Full class context (methods often depend on fields) -- Import statements (crucial for compilation) -- Package declarations -- Type hierarchy (extends/implements) -- Inner classes -- Static imports - -```python -def extract_code_context( - function: FunctionInfo, - project_root: Path, - module_root: Path | None = None -) -> CodeContext: - """ - Extract code context for a Java method. - - Context includes: - 1. Full containing class (target method needs class context) - 2. All imports from the file - 3. Helper classes from same package - 4. Superclass/interface definitions (read-only) - """ - source = function.file_path.read_text(encoding="utf-8") - parser = JavaParser() - - # Extract package and imports - package_name = parser.get_package(source) - imports = parser.get_imports(source) - - # Get the containing class - class_source = parser.extract_class_containing_method( - source, function.name, function.start_line - ) - - # Find helper classes (same package, used by target class) - helper_classes = find_helper_classes( - function.file_path.parent, - class_source, - imports - ) - - return CodeContext( - target_code=class_source, - target_file=function.file_path, - helper_functions=helper_classes, - read_only_context=get_superclass_context(imports, project_root), - imports=imports, - language=Language.JAVA, - ) -``` - -### 3.4 Import/Dependency Resolution - -**File: `codeflash/languages/java/import_resolver.py`** - -Java import resolution is more complex: -- Explicit imports (`import com.foo.Bar;`) -- Wildcard imports (`import com.foo.*;`) -- Static imports (`import static com.foo.Bar.method;`) -- Same-package classes (implicit) -- Standard library vs external dependencies - -```python -class JavaImportResolver: - """Resolve Java imports to source files.""" - - def __init__(self, project_root: Path, build_tool: BuildTool): - self.project_root = project_root - self.build_tool = build_tool - self.source_roots = self._find_source_roots() - self.classpath = build_tool.get_classpath() - - def resolve_import(self, import_stmt: str) -> ResolvedImport: - """ - Resolve an import to its source location. - - Returns: - - Source file path (if in project) - - JAR location (if external dependency) - - None (if JDK class) - """ - ... - - def find_same_package_classes(self, package: str) -> list[Path]: - """Find all classes in the same package.""" - ... -``` - -### 3.5 Test Discovery - -**File: `codeflash/languages/java/support.py` (part of JavaSupport)** - -Java test discovery for JUnit 5: - -```python -def discover_tests( - self, - test_root: Path, - source_functions: list[FunctionInfo] -) -> dict[str, list[TestInfo]]: - """ - Discover JUnit tests that cover target methods. - - Strategy: - 1. Find test files by naming convention (*Test.java, *Tests.java) - 2. Parse test files for @Test annotated methods - 3. Analyze test code for method calls to target methods - 4. Match tests to source methods - """ - test_files = self._find_test_files(test_root) - test_map: dict[str, list[TestInfo]] = defaultdict(list) - - for test_file in test_files: - parser = JavaParser() - source = test_file.read_text() - - for test_method in parser.find_test_methods(source): - # Find which source methods this test calls - called_methods = parser.find_method_calls(test_method.body) - - for source_func in source_functions: - if source_func.name in called_methods: - test_map[source_func.qualified_name].append(TestInfo( - test_name=test_method.name, - test_file=test_file, - test_class=test_method.class_name, - )) - - return test_map -``` - -### 3.6 Test Execution - -**File: `codeflash/languages/java/test_runner.py`** - -JUnit test execution with Maven/Gradle: - -```python -class JavaTestRunner: - """Run JUnit tests via Maven or Gradle.""" - - def __init__(self, project_root: Path): - self.build_tool = detect_build_tool(project_root) - self.project_root = project_root - - def run_tests( - self, - test_classes: list[str], - timeout: int = 60, - capture_output: bool = True - ) -> TestExecutionResult: - """ - Run specified JUnit tests. - - Uses: - - Maven: mvn test -Dtest=ClassName#methodName - - Gradle: ./gradlew test --tests "ClassName.methodName" - """ - if self.build_tool == BuildTool.MAVEN: - return self._run_maven_tests(test_classes, timeout) - else: - return self._run_gradle_tests(test_classes, timeout) - - def _run_maven_tests(self, tests: list[str], timeout: int) -> TestExecutionResult: - cmd = [ - "mvn", "test", - f"-Dtest={','.join(tests)}", - "-Dmaven.test.failure.ignore=true", - "-DfailIfNoTests=false", - ] - result = subprocess.run(cmd, cwd=self.project_root, ...) - return self._parse_surefire_reports() - - def _parse_surefire_reports(self) -> TestExecutionResult: - """Parse target/surefire-reports/*.xml for test results.""" - ... -``` - -### 3.7 Code Instrumentation - -**File: `codeflash/languages/java/instrument.py`** - -Java instrumentation for behavior capture: - -```python -class JavaInstrumenter: - """Instrument Java code for behavior/performance capture.""" - - def instrument_for_behavior( - self, - source: str, - target_methods: list[str] - ) -> str: - """ - Add instrumentation to capture method inputs/outputs. - - Adds: - - CodeFlash.captureInput(args) before method body - - CodeFlash.captureOutput(result) before returns - - Exception capture in catch blocks - """ - parser = JavaParser() - tree = parser.parse(source) - - # Insert capture calls using tree-sitter edit operations - edits = [] - for method in parser.find_methods_by_name(tree, target_methods): - edits.append(self._create_input_capture(method)) - edits.append(self._create_output_capture(method)) - - return apply_edits(source, edits) - - def instrument_for_benchmarking( - self, - test_source: str, - target_method: str, - iterations: int = 1000 - ) -> str: - """ - Add timing instrumentation to test code. - - Wraps test execution in timing loop with warmup. - """ - ... -``` - -### 3.8 Build Tool Integration - -**File: `codeflash/languages/java/build_tools.py`** - -Maven and Gradle support: - -```python -class BuildTool(Enum): - MAVEN = "maven" - GRADLE = "gradle" - -def detect_build_tool(project_root: Path) -> BuildTool: - """Detect whether project uses Maven or Gradle.""" - if (project_root / "pom.xml").exists(): - return BuildTool.MAVEN - elif (project_root / "build.gradle").exists() or \ - (project_root / "build.gradle.kts").exists(): - return BuildTool.GRADLE - raise ValueError("No Maven or Gradle build file found") - -class MavenIntegration: - """Maven build tool integration.""" - - def __init__(self, project_root: Path): - self.pom_path = project_root / "pom.xml" - self.project_root = project_root - - def get_source_roots(self) -> list[Path]: - """Get configured source directories.""" - # Default: src/main/java, src/test/java - ... - - def get_classpath(self) -> list[Path]: - """Get full classpath including dependencies.""" - result = subprocess.run( - ["mvn", "dependency:build-classpath", "-q", "-DincludeScope=test"], - cwd=self.project_root, - capture_output=True - ) - return [Path(p) for p in result.stdout.decode().split(":")] - - def compile(self, include_tests: bool = True) -> bool: - """Compile the project.""" - cmd = ["mvn", "compile"] - if include_tests: - cmd.append("test-compile") - return subprocess.run(cmd, cwd=self.project_root).returncode == 0 - -class GradleIntegration: - """Gradle build tool integration.""" - # Similar implementation for Gradle - ... -``` - -### 3.9 Code Replacement - -**File: `codeflash/languages/java/support.py`** - -```python -def replace_function( - self, - source: str, - function: FunctionInfo, - new_source: str -) -> str: - """ - Replace a method in Java source code. - - Challenges: - - Method might have annotations - - Javadoc comments should be preserved/updated - - Overloaded methods need exact signature matching - """ - parser = JavaParser() - - # Find the exact method by line number (handles overloads) - method_node = parser.find_method_at_line(source, function.start_line) - - # Include Javadoc if present - start = method_node.javadoc_start or method_node.start - end = method_node.end - - # Replace the method - return source[:start] + new_source + source[end:] -``` - -### 3.10 Code Formatting - -**File: `codeflash/languages/java/formatter.py`** - -```python -def format_code(source: str, file_path: Path | None = None) -> str: - """ - Format Java code using google-java-format. - - Falls back to built-in formatter if google-java-format not available. - """ - try: - result = subprocess.run( - ["google-java-format", "-"], - input=source.encode(), - capture_output=True, - timeout=30 - ) - if result.returncode == 0: - return result.stdout.decode() - except FileNotFoundError: - pass - - # Fallback: basic indentation normalization - return normalize_indentation(source) -``` - ---- - -## 4. Test Result Comparison - -### 4.1 Behavior Verification - -For Java, test results comparison needs to handle: -- Object equality (`.equals()` vs reference equality) -- Collection ordering (Lists vs Sets) -- Floating point comparison with epsilon -- Exception messages and types -- Side effects (mocked interactions) - -```python -# codeflash/languages/java/comparator.py - -def compare_test_results( - original_results: Path, - candidate_results: Path, - project_root: Path -) -> tuple[bool, list[TestDiff]]: - """ - Compare behavior between original and optimized code. - - Uses a Java comparison utility (run via the build tool) - that handles Java-specific equality semantics. - """ - # Run Java-based comparison tool - result = subprocess.run([ - "java", "-cp", get_comparison_jar(), - "com.codeflash.Comparator", - str(original_results), - str(candidate_results) - ], capture_output=True) - - diffs = json.loads(result.stdout) - return len(diffs) == 0, [TestDiff(**d) for d in diffs] -``` - ---- - -## 5. AI Service Integration - -The AI service already supports language parameter. For Java: - -```python -# Called from function_optimizer.py -response = ai_service.optimize_code( - source_code=code_context.target_code, - dependency_code=code_context.read_only_context, - trace_id=trace_id, - language="java", - language_version="17", # or "11", "21" - n_candidates=5, -) -``` - -Java-specific optimization prompts should consider: -- Stream API optimizations -- Collection choice (ArrayList vs LinkedList, HashMap vs TreeMap) -- Concurrency patterns (CompletableFuture, parallel streams) -- Memory optimization (primitive vs boxed types) -- JIT-friendly patterns - ---- - -## 6. Configuration Detection - -**File: `codeflash/languages/java/config.py`** - -```python -def detect_java_version(project_root: Path) -> str: - """Detect Java version from build configuration.""" - build_tool = detect_build_tool(project_root) - - if build_tool == BuildTool.MAVEN: - # Check pom.xml for maven.compiler.source - pom = ET.parse(project_root / "pom.xml") - version = pom.find(".//maven.compiler.source") - if version is not None: - return version.text - - elif build_tool == BuildTool.GRADLE: - # Check build.gradle for sourceCompatibility - build_file = project_root / "build.gradle" - if build_file.exists(): - content = build_file.read_text() - match = re.search(r"sourceCompatibility\s*=\s*['\"]?(\d+)", content) - if match: - return match.group(1) - - # Fallback: detect from JAVA_HOME - return detect_jdk_version() - -def detect_source_roots(project_root: Path) -> list[Path]: - """Find source code directories.""" - standard_paths = [ - project_root / "src" / "main" / "java", - project_root / "src", - ] - return [p for p in standard_paths if p.exists()] - -def detect_test_roots(project_root: Path) -> list[Path]: - """Find test code directories.""" - standard_paths = [ - project_root / "src" / "test" / "java", - project_root / "test", - ] - return [p for p in standard_paths if p.exists()] -``` - ---- - -## 7. Runtime Library - -CodeFlash needs a Java runtime library for instrumentation: - -``` -codeflash-runtime-java/ -├── pom.xml -├── src/main/java/com/codeflash/ -│ ├── CodeFlash.java # Main capture API -│ ├── Capture.java # Input/output capture -│ ├── Comparator.java # Result comparison -│ ├── Timer.java # High-precision timing -│ └── Serializer.java # Object serialization for comparison -``` - -```java -// CodeFlash.java -package com.codeflash; - -public class CodeFlash { - public static void captureInput(String methodId, Object... args) { - // Serialize and store inputs - } - - public static T captureOutput(String methodId, T result) { - // Serialize and store output - return result; - } - - public static void captureException(String methodId, Throwable e) { - // Store exception info - } - - public static long startTimer() { - return System.nanoTime(); - } - - public static void recordTime(String methodId, long startTime) { - long elapsed = System.nanoTime() - startTime; - // Store timing - } -} -``` - ---- - -## 8. Implementation Phases - -### Phase 1: Foundation (MVP) - -1. Add `Language.JAVA` to enum -2. Implement tree-sitter Java parsing -3. Basic method discovery (public methods in classes) -4. Build tool detection (Maven/Gradle) -5. Simple context extraction (single file) -6. Test discovery (JUnit 5 `@Test` methods) -7. Test execution via Maven/Gradle - -### Phase 2: Full Pipeline - -1. Import resolution and dependency tracking -2. Multi-file context extraction -3. Test result capture and comparison -4. Code instrumentation for behavior verification -5. Benchmarking instrumentation -6. Code formatting integr.ation - -### Phase 3: Advanced Features - -1. Line profiler integration (JProfiler/async-profiler) -2. Generics handling in optimization -3. Lambda and stream optimization support -4. Concurrency-aware benchmarking -5. IDE integration (Language Server) - ---- - -## 9. Key Challenges & Considerations - -### 9.1 Java-Specific Challenges - -| Challenge | Solution | -|-----------|----------| -| **No top-level functions** | Always include class context | -| **Overloaded methods** | Use full signature for identification | -| **Compilation required** | Compile before running tests | -| **Build tool complexity** | Abstract via `BuildTool` interface | -| **Static typing** | Ensure type compatibility in replacements | -| **Generics** | Preserve type parameters in optimization | -| **Checked exceptions** | Maintain throws declarations | -| **Package visibility** | Handle package-private methods | - -### 9.2 Performance Considerations - -- **JVM Warmup**: Java needs JIT warmup before benchmarking -- **GC Noise**: Account for garbage collection in timing -- **Classloading**: First run is always slower - -```python -def run_benchmark_with_warmup( - test_method: str, - warmup_iterations: int = 100, - benchmark_iterations: int = 1000 -) -> BenchmarkResult: - """Run benchmark with proper JVM warmup.""" - # Warmup phase (results discarded) - run_tests(test_method, iterations=warmup_iterations) - - # Force GC before measurement - subprocess.run(["jcmd", str(pid), "GC.run"]) - - # Actual benchmark - return run_tests(test_method, iterations=benchmark_iterations) -``` - -### 9.3 Test Framework Support - -| Framework | Priority | Notes | -|-----------|----------|-------| -| JUnit 5 | High | Primary target, most modern | -| JUnit 4 | Medium | Still widely used | -| TestNG | Low | Different annotation model | -| Mockito | High | Mocking support needed | -| AssertJ | Medium | Fluent assertions | - ---- - -## 10. File Changes Summary - -### New Files to Create - -``` -codeflash/languages/java/ -├── __init__.py -├── support.py (~800 lines) -├── parser.py (~400 lines) -├── discovery.py (~300 lines) -├── context_extractor.py (~400 lines) -├── import_resolver.py (~350 lines) -├── instrument.py (~500 lines) -├── test_runner.py (~400 lines) -├── comparator.py (~200 lines) -├── build_tools.py (~350 lines) -├── formatter.py (~100 lines) -├── line_profiler.py (~300 lines) -└── config.py (~150 lines) -Total: ~4,250 lines -``` - -### Existing Files to Modify - -| File | Changes | -|------|---------| -| `codeflash/languages/base.py` | Add `JAVA` to `Language` enum | -| `codeflash/languages/__init__.py` | Import java module | -| `codeflash/cli_cmds/init.py` | Add Java project detection | -| `codeflash/api/aiservice.py` | No changes (already supports `language` param) | -| `requirements.txt` / `pyproject.toml` | Add `tree-sitter-java` | - -### External Dependencies - -```toml -# pyproject.toml additions -tree-sitter-java = "^0.21.0" -``` - ---- - -## 11. Testing Strategy - -### Unit Tests - -```python -# tests/languages/java/test_parser.py -def test_discover_methods_in_class(): - source = ''' - public class Calculator { - public int add(int a, int b) { - return a + b; - } - } - ''' - methods = JavaParser().find_methods(source) - assert len(methods) == 1 - assert methods[0].name == "add" - -# tests/languages/java/test_discovery.py -def test_discover_functions_filters_tests(): - # Test that test methods are excluded - ... -``` - -### Integration Tests - -```python -# tests/languages/java/test_integration.py -def test_full_optimization_pipeline(java_test_project): - """End-to-end test with a real Java project.""" - support = JavaSupport() - - functions = support.discover_functions( - java_test_project / "src/main/java/Example.java" - ) - - context = support.extract_code_context(functions[0], java_test_project) - - # Verify context is compilable - assert compile_java(context.target_code) -``` - ---- - -## 12. LanguageSupport Protocol Reference - -All methods that `JavaSupport` must implement: - -### Properties - -```python -@property -def language(self) -> Language: ... - -@property -def file_extensions(self) -> tuple[str, ...]: ... - -@property -def test_framework(self) -> str: ... - -@property -def comment_prefix(self) -> str: ... -``` - -### Discovery Methods - -```python -def discover_functions( - self, - file_path: Path, - criteria: FunctionFilterCriteria | None = None -) -> list[FunctionInfo]: ... - -def discover_tests( - self, - test_root: Path, - source_functions: list[FunctionInfo] -) -> dict[str, list[TestInfo]]: ... -``` - -### Code Analysis - -```python -def extract_code_context( - self, - function: FunctionInfo, - project_root: Path, - module_root: Path | None = None -) -> CodeContext: ... - -def find_helper_functions( - self, - function: FunctionInfo, - project_root: Path -) -> list[HelperFunction]: ... -``` - -### Code Transformation - -```python -def replace_function( - self, - source: str, - function: FunctionInfo, - new_source: str -) -> str: ... - -def format_code( - self, - source: str, - file_path: Path | None = None -) -> str: ... - -def normalize_code(self, source: str) -> str: ... -``` - -### Test Execution - -```python -def run_behavioral_tests( - self, - test_paths: list[Path], - test_env: dict[str, str], - cwd: Path, - timeout: int, - ... -) -> tuple[Path, Any, Path | None, Path | None]: ... - -def run_benchmarking_tests( - self, - test_paths: list[Path], - test_env: dict[str, str], - cwd: Path, - timeout: int, - ... -) -> tuple[Path, Any]: ... -``` - -### Instrumentation - -```python -def instrument_for_behavior( - self, - source: str, - functions: list[str] -) -> str: ... - -def instrument_for_benchmarking( - self, - test_source: str, - target_function: str -) -> str: ... - -def instrument_existing_test( - self, - test_path: Path, - call_positions: list[tuple[int, int]], - ... -) -> tuple[bool, str | None]: ... -``` - -### Validation - -```python -def validate_syntax(self, source: str) -> bool: ... -``` - -### Result Comparison - -```python -def compare_test_results( - self, - original_path: Path, - candidate_path: Path, - project_root: Path -) -> tuple[bool, list[TestDiff]]: ... -``` - ---- - -## 13. Data Flow Diagram - -``` -┌──────────────────────────────────────────────────────────────────────────┐ -│ Java Optimization Flow │ -└──────────────────────────────────────────────────────────────────────────┘ - -User runs: codeflash optimize Example.java - │ - ▼ - ┌───────────────────────────────┐ - │ Detect Build Tool │ - │ (Maven pom.xml / Gradle) │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Discover Methods │ - │ (tree-sitter-java parsing) │ - │ Filter: public, non-test │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Extract Code Context │ - │ - Full class with imports │ - │ - Helper classes (same pkg) │ - │ - Superclass definitions │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Discover Tests │ - │ - Find *Test.java files │ - │ - Parse @Test annotations │ - │ - Match to source methods │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Run Baseline │ - │ - Compile (mvn/gradle) │ - │ - Execute JUnit tests │ - │ - Capture behavior + timing │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ AI Optimization │ - │ - Send to AI service │ - │ - language="java" │ - │ - Receive N candidates │ - └───────────────┬───────────────┘ - │ - ┌───────────┴───────────┐ - ▼ ▼ -┌───────────────┐ ┌───────────────┐ -│ Candidate 1 │ ... │ Candidate N │ -└───────┬───────┘ └───────┬───────┘ - │ │ - └───────────┬───────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ For Each Candidate: │ - │ 1. Replace method in source │ - │ 2. Compile project │ - │ 3. Run behavior tests │ - │ 4. Compare outputs │ - │ 5. If correct: benchmark │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Select Best Candidate │ - │ - Correctness verified │ - │ - Best speedup │ - │ - Account for JVM warmup │ - └───────────────┬───────────────┘ - │ - ▼ - ┌───────────────────────────────┐ - │ Apply Optimization │ - │ - Update source file │ - │ - Create PR (optional) │ - │ - Report results │ - └───────────────────────────────┘ -``` - ---- - -## 14. Conclusion - -This architecture provides a comprehensive roadmap for adding Java support to CodeFlash. The modular design mirrors the existing JavaScript/TypeScript implementation pattern, making it straightforward to implement incrementally while maintaining consistency with the rest of the codebase. - -Key success factors: -1. **Leverage tree-sitter** for consistent parsing approach -2. **Abstract build tools** to support both Maven and Gradle -3. **Handle JVM specifics** (warmup, GC) in benchmarking -4. **Reuse existing infrastructure** where possible (AI service, result types) -5. **Implement incrementally** following the phased approach \ No newline at end of file