mirror of
https://github.com/codeflash-ai/codeflash-internal.git
synced 2026-05-04 18:25:18 +00:00
cleanup
This commit is contained in:
parent
dcac02b3f2
commit
31091350c9
13 changed files with 30 additions and 831 deletions
|
|
@ -10,9 +10,6 @@ import re
|
|||
|
||||
from aiservice.common.llm_output_utils import truncate_pathological_output
|
||||
|
||||
# Matches ```python:filepath blocks, captures (filepath, content)
|
||||
MARKDOWN_CODE_BLOCK_WITH_PATH_PATTERN = re.compile(r"```python:([^\n]+)\n(.*?)\n```", re.DOTALL)
|
||||
|
||||
# Matches both ```python and ```python:filepath blocks, captures content only
|
||||
MARKDOWN_CODE_BLOCK_PATTERN = re.compile(r"```python(?::[^\n]*)?\n(.*?)```", re.DOTALL)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from functools import lru_cache
|
|||
@lru_cache(maxsize=100)
|
||||
def validate_javascript_syntax(code: str) -> tuple[bool, str | None]:
|
||||
# TODO(claude): DON'T do this, use some pytohn lib for this instead of spawning a new subprocess
|
||||
# Note: code can be a multi-file code (markdown with file paths)
|
||||
return True, None
|
||||
"""Validate JavaScript syntax using Node.js.
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ class CodeRepairContext:
|
|||
def validate_module(self) -> None:
|
||||
"""Validate the module syntax based on language."""
|
||||
# Skip validation for non-Python languages for now
|
||||
# TODO: have some way to validate the syntax of the code for other languages like js & ts
|
||||
if self.data.language != "python":
|
||||
return
|
||||
for _code in split_markdown_code(self.data.modified_source_code).values():
|
||||
|
|
@ -147,7 +148,3 @@ class CodeRepairContext:
|
|||
CodeAndExplanation(cst_module, "")
|
||||
except (ValueError, ValidationError, cst.ParserSyntaxError): # noqa: TRY203
|
||||
raise
|
||||
|
||||
# Keep for backward compatibility
|
||||
def validate_python_module(self) -> None:
|
||||
self.validate_module()
|
||||
|
|
|
|||
|
|
@ -1,146 +1,8 @@
|
|||
"""Multi-language support registry.
|
||||
"""Multi-language support module.
|
||||
|
||||
This module provides a registry for language implementations and factory
|
||||
functions to retrieve language-specific functionality.
|
||||
This package contains language-specific implementations for code optimization
|
||||
and test generation.
|
||||
|
||||
Usage:
|
||||
from languages import get_language, register_language
|
||||
|
||||
# Get a language implementation
|
||||
lang = get_language("python")
|
||||
validator = lang.get_validator()
|
||||
is_valid, error = validator.validate_syntax(code)
|
||||
|
||||
# Register a new language (typically done in language module __init__)
|
||||
@register_language("python")
|
||||
class PythonLanguage:
|
||||
...
|
||||
Subpackages:
|
||||
js_ts: JavaScript and TypeScript support
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from languages.base import LanguageSupport
|
||||
|
||||
# Registry mapping language identifiers to their implementation classes
|
||||
_LANGUAGE_REGISTRY: dict[str, type[LanguageSupport]] = {}
|
||||
|
||||
# Aliases for language names (e.g., "js" -> "javascript")
|
||||
_LANGUAGE_ALIASES: dict[str, str] = {
|
||||
"js": "javascript",
|
||||
"ts": "typescript",
|
||||
}
|
||||
|
||||
# Flag to track whether languages have been loaded
|
||||
_languages_loaded = False
|
||||
|
||||
|
||||
class UnsupportedLanguageError(ValueError):
|
||||
"""Raised when an unsupported language is requested."""
|
||||
|
||||
def __init__(self, language: str) -> None:
|
||||
supported = ", ".join(sorted(_LANGUAGE_REGISTRY.keys()))
|
||||
super().__init__(f"Unsupported language: {language}. Supported languages: {supported}")
|
||||
self.language = language
|
||||
|
||||
|
||||
def register_language(lang_id: str):
|
||||
"""Decorator to register a language implementation.
|
||||
|
||||
Args:
|
||||
lang_id: The language identifier (e.g., "python", "javascript").
|
||||
|
||||
Returns:
|
||||
A decorator that registers the class in the language registry.
|
||||
|
||||
Example:
|
||||
@register_language("python")
|
||||
class PythonLanguage:
|
||||
language = "python"
|
||||
...
|
||||
|
||||
"""
|
||||
|
||||
def decorator(cls: type[LanguageSupport]) -> type[LanguageSupport]:
|
||||
_LANGUAGE_REGISTRY[lang_id] = cls
|
||||
return cls
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def _load_languages() -> None:
|
||||
"""Load all language implementations.
|
||||
|
||||
This is called lazily to avoid import issues during module initialization.
|
||||
"""
|
||||
# Import Python language support
|
||||
try:
|
||||
import languages.python # noqa: F401
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Import JavaScript/TypeScript language support
|
||||
try:
|
||||
import languages.js_ts # noqa: F401
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
def _ensure_languages_loaded() -> None:
|
||||
"""Ensure language implementations are loaded."""
|
||||
global _languages_loaded
|
||||
if not _languages_loaded:
|
||||
_load_languages()
|
||||
_languages_loaded = True
|
||||
|
||||
|
||||
def get_language(language: str) -> LanguageSupport:
|
||||
"""Get language support implementation for the given language.
|
||||
|
||||
Args:
|
||||
language: The language identifier (e.g., "python", "javascript", "js").
|
||||
|
||||
Returns:
|
||||
An instance of the language support class.
|
||||
|
||||
Raises:
|
||||
UnsupportedLanguageError: If the language is not registered.
|
||||
|
||||
"""
|
||||
_ensure_languages_loaded()
|
||||
|
||||
# Normalize language identifier using aliases
|
||||
normalized = _LANGUAGE_ALIASES.get(language.lower(), language.lower())
|
||||
|
||||
if normalized not in _LANGUAGE_REGISTRY:
|
||||
raise UnsupportedLanguageError(language)
|
||||
|
||||
return _LANGUAGE_REGISTRY[normalized]()
|
||||
|
||||
|
||||
def get_supported_languages() -> list[str]:
|
||||
"""Get a list of supported language identifiers.
|
||||
|
||||
Returns:
|
||||
A sorted list of supported language names.
|
||||
|
||||
"""
|
||||
_ensure_languages_loaded()
|
||||
return sorted(_LANGUAGE_REGISTRY.keys())
|
||||
|
||||
|
||||
def is_language_supported(language: str) -> bool:
|
||||
"""Check if a language is supported.
|
||||
|
||||
Args:
|
||||
language: The language identifier to check.
|
||||
|
||||
Returns:
|
||||
True if the language is supported, False otherwise.
|
||||
|
||||
"""
|
||||
_ensure_languages_loaded()
|
||||
normalized = _LANGUAGE_ALIASES.get(language.lower(), language.lower())
|
||||
return normalized in _LANGUAGE_REGISTRY
|
||||
|
|
|
|||
|
|
@ -1,98 +0,0 @@
|
|||
"""Base protocols and interfaces for multi-language support.
|
||||
|
||||
This module defines the contracts that language implementations must satisfy.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Protocol, runtime_checkable
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class CodeValidator(Protocol):
|
||||
"""Protocol for code syntax validation."""
|
||||
|
||||
def validate_syntax(self, code: str) -> tuple[bool, str | None]:
|
||||
"""Validate code syntax.
|
||||
|
||||
Args:
|
||||
code: The source code to validate.
|
||||
|
||||
Returns:
|
||||
A tuple of (is_valid, error_message).
|
||||
- is_valid: True if the code is syntactically valid.
|
||||
- error_message: None if valid, otherwise a description of the error.
|
||||
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class LanguageSupport(Protocol):
|
||||
"""Protocol for language-specific implementations.
|
||||
|
||||
Each supported language should implement this protocol to provide
|
||||
language-specific functionality like validation and code formatting.
|
||||
"""
|
||||
|
||||
@property
|
||||
def language(self) -> str:
|
||||
"""The language identifier (e.g., 'python', 'javascript')."""
|
||||
...
|
||||
|
||||
def get_validator(self) -> CodeValidator:
|
||||
"""Get the code validator for this language."""
|
||||
...
|
||||
|
||||
def is_multi_context(self, code: str) -> bool:
|
||||
"""Check if code is in multi-file markdown format.
|
||||
|
||||
Multi-file format uses ```language:filepath blocks.
|
||||
|
||||
Args:
|
||||
code: The source code to check.
|
||||
|
||||
Returns:
|
||||
True if the code is in multi-file markdown format.
|
||||
|
||||
"""
|
||||
...
|
||||
|
||||
def get_code_block_tag(self) -> str:
|
||||
"""Get the markdown code block tag for this language.
|
||||
|
||||
Returns:
|
||||
The language tag used in markdown code blocks (e.g., 'python', 'javascript').
|
||||
|
||||
"""
|
||||
...
|
||||
|
||||
def split_markdown_code(self, markdown: str) -> dict[str, str]:
|
||||
"""Split markdown into filepath -> code dict.
|
||||
|
||||
Parses markdown with ```language:filepath blocks and returns
|
||||
a dictionary mapping file paths to their code content.
|
||||
|
||||
Args:
|
||||
markdown: The markdown text containing code blocks.
|
||||
|
||||
Returns:
|
||||
A dictionary mapping file paths to code content.
|
||||
|
||||
"""
|
||||
...
|
||||
|
||||
def group_code(self, file_to_code: dict[str, str]) -> str:
|
||||
"""Combine code files into markdown format.
|
||||
|
||||
Args:
|
||||
file_to_code: A dictionary mapping file paths to code content.
|
||||
|
||||
Returns:
|
||||
Markdown-formatted string with code blocks for each file.
|
||||
|
||||
"""
|
||||
...
|
||||
|
|
@ -1,204 +1,17 @@
|
|||
"""JavaScript/TypeScript language support for the aiservice.
|
||||
"""JavaScript/TypeScript language support.
|
||||
|
||||
This module provides JS/TS-specific implementations for code validation,
|
||||
multi-file context detection, and code formatting.
|
||||
|
||||
Note: The full implementation will be moved here from optimizer_javascript.py
|
||||
and testgen_javascript.py in Phase 3.
|
||||
This package contains JS/TS-specific implementations for:
|
||||
- Code optimization (optimizer.py)
|
||||
- Line profiler optimization (optimizer_lp.py)
|
||||
- Test generation (testgen.py)
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from languages.js_ts.optimizer import optimize_javascript
|
||||
from languages.js_ts.optimizer_lp import optimize_javascript_code_line_profiler
|
||||
from languages.js_ts.testgen import testgen_javascript
|
||||
|
||||
from aiservice.common.markdown_utils import split_markdown_code as _split_markdown_code
|
||||
|
||||
from languages import register_language
|
||||
|
||||
|
||||
class JavaScriptValidator:
|
||||
"""Validator for JavaScript code syntax.
|
||||
|
||||
Note: Currently uses a permissive fallback validation.
|
||||
Full validation will be implemented in a future PR.
|
||||
"""
|
||||
|
||||
def validate_syntax(self, code: str) -> tuple[bool, str | None]:
|
||||
"""Validate JavaScript syntax.
|
||||
|
||||
Args:
|
||||
code: The JavaScript code to validate.
|
||||
|
||||
Returns:
|
||||
A tuple of (is_valid, error_message).
|
||||
|
||||
Note:
|
||||
Currently returns (True, None) as a permissive default.
|
||||
The full validation logic from javascript_validator.py
|
||||
will be integrated in Phase 3.
|
||||
|
||||
"""
|
||||
# TODO: Integrate full validation from aiservice/validators/javascript_validator.py
|
||||
# For now, use permissive validation to match current behavior
|
||||
return True, None
|
||||
|
||||
|
||||
class TypeScriptValidator:
|
||||
"""Validator for TypeScript code syntax.
|
||||
|
||||
Note: Currently uses a permissive fallback validation.
|
||||
Full validation will be implemented in a future PR.
|
||||
"""
|
||||
|
||||
def validate_syntax(self, code: str) -> tuple[bool, str | None]:
|
||||
"""Validate TypeScript syntax.
|
||||
|
||||
Args:
|
||||
code: The TypeScript code to validate.
|
||||
|
||||
Returns:
|
||||
A tuple of (is_valid, error_message).
|
||||
|
||||
Note:
|
||||
Currently returns (True, None) as a permissive default.
|
||||
The full validation logic will be integrated in Phase 3.
|
||||
|
||||
"""
|
||||
# TODO: Integrate full validation from aiservice/validators/javascript_validator.py
|
||||
return True, None
|
||||
|
||||
|
||||
@register_language("javascript")
|
||||
class JavaScriptLanguage:
|
||||
"""JavaScript language support implementation."""
|
||||
|
||||
@property
|
||||
def language(self) -> str:
|
||||
"""The language identifier."""
|
||||
return "javascript"
|
||||
|
||||
def get_validator(self) -> JavaScriptValidator:
|
||||
"""Get the JavaScript code validator."""
|
||||
return JavaScriptValidator()
|
||||
|
||||
def is_multi_context(self, code: str) -> bool:
|
||||
"""Check if code is in multi-file markdown format.
|
||||
|
||||
Multi-file JavaScript code starts with ```javascript: or ```js:
|
||||
followed by a filepath.
|
||||
|
||||
Args:
|
||||
code: The source code to check.
|
||||
|
||||
Returns:
|
||||
True if the code is in multi-file markdown format.
|
||||
|
||||
"""
|
||||
stripped = code.strip()
|
||||
return stripped.startswith("```javascript:") or stripped.startswith("```js:")
|
||||
|
||||
def get_code_block_tag(self) -> str:
|
||||
"""Get the markdown code block tag for JavaScript.
|
||||
|
||||
Returns:
|
||||
The string 'javascript' used in markdown code blocks.
|
||||
|
||||
"""
|
||||
return "javascript"
|
||||
|
||||
def split_markdown_code(self, markdown: str) -> dict[str, str]:
|
||||
"""Split markdown into filepath -> code dict.
|
||||
|
||||
Parses markdown with ```javascript:filepath or ```js:filepath blocks.
|
||||
|
||||
Args:
|
||||
markdown: The markdown text containing code blocks.
|
||||
|
||||
Returns:
|
||||
A dictionary mapping file paths to code content.
|
||||
|
||||
"""
|
||||
return _split_markdown_code(markdown, language="javascript")
|
||||
|
||||
def group_code(self, file_to_code: dict[str, str]) -> str:
|
||||
"""Combine code files into markdown format.
|
||||
|
||||
Args:
|
||||
file_to_code: A dictionary mapping file paths to code content.
|
||||
|
||||
Returns:
|
||||
Markdown-formatted string with ```javascript:filepath blocks.
|
||||
|
||||
"""
|
||||
blocks = []
|
||||
for file_path, code in file_to_code.items():
|
||||
normalized = code if code.endswith("\n") else code + "\n"
|
||||
blocks.append(f"```javascript:{file_path}\n{normalized}```")
|
||||
return "\n".join(blocks)
|
||||
|
||||
|
||||
@register_language("typescript")
|
||||
class TypeScriptLanguage:
|
||||
"""TypeScript language support implementation."""
|
||||
|
||||
@property
|
||||
def language(self) -> str:
|
||||
"""The language identifier."""
|
||||
return "typescript"
|
||||
|
||||
def get_validator(self) -> TypeScriptValidator:
|
||||
"""Get the TypeScript code validator."""
|
||||
return TypeScriptValidator()
|
||||
|
||||
def is_multi_context(self, code: str) -> bool:
|
||||
"""Check if code is in multi-file markdown format.
|
||||
|
||||
Multi-file TypeScript code starts with ```typescript: or ```ts:
|
||||
followed by a filepath.
|
||||
|
||||
Args:
|
||||
code: The source code to check.
|
||||
|
||||
Returns:
|
||||
True if the code is in multi-file markdown format.
|
||||
|
||||
"""
|
||||
stripped = code.strip()
|
||||
return stripped.startswith("```typescript:") or stripped.startswith("```ts:")
|
||||
|
||||
def get_code_block_tag(self) -> str:
|
||||
"""Get the markdown code block tag for TypeScript.
|
||||
|
||||
Returns:
|
||||
The string 'typescript' used in markdown code blocks.
|
||||
|
||||
"""
|
||||
return "typescript"
|
||||
|
||||
def split_markdown_code(self, markdown: str) -> dict[str, str]:
|
||||
"""Split markdown into filepath -> code dict.
|
||||
|
||||
Parses markdown with ```typescript:filepath or ```ts:filepath blocks.
|
||||
|
||||
Args:
|
||||
markdown: The markdown text containing code blocks.
|
||||
|
||||
Returns:
|
||||
A dictionary mapping file paths to code content.
|
||||
|
||||
"""
|
||||
return _split_markdown_code(markdown, language="typescript")
|
||||
|
||||
def group_code(self, file_to_code: dict[str, str]) -> str:
|
||||
"""Combine code files into markdown format.
|
||||
|
||||
Args:
|
||||
file_to_code: A dictionary mapping file paths to code content.
|
||||
|
||||
Returns:
|
||||
Markdown-formatted string with ```typescript:filepath blocks.
|
||||
|
||||
"""
|
||||
blocks = []
|
||||
for file_path, code in file_to_code.items():
|
||||
normalized = code if code.endswith("\n") else code + "\n"
|
||||
blocks.append(f"```typescript:{file_path}\n{normalized}```")
|
||||
return "\n".join(blocks)
|
||||
__all__ = [
|
||||
"optimize_javascript",
|
||||
"optimize_javascript_code_line_profiler",
|
||||
"testgen_javascript",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
"""Python language support for the aiservice.
|
||||
|
||||
This module provides Python-specific implementations for code validation,
|
||||
multi-file context detection, and code formatting.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from aiservice.common.markdown_utils import split_markdown_code as _split_markdown_code
|
||||
from languages import register_language
|
||||
from languages.python.validator import PythonValidator
|
||||
|
||||
|
||||
@register_language("python")
|
||||
class PythonLanguage:
|
||||
"""Python language support implementation."""
|
||||
|
||||
@property
|
||||
def language(self) -> str:
|
||||
"""The language identifier."""
|
||||
return "python"
|
||||
|
||||
def get_validator(self) -> PythonValidator:
|
||||
"""Get the Python code validator."""
|
||||
return PythonValidator()
|
||||
|
||||
def is_multi_context(self, code: str) -> bool:
|
||||
"""Check if code is in multi-file markdown format.
|
||||
|
||||
Multi-file Python code starts with ```python: followed by a filepath.
|
||||
|
||||
Args:
|
||||
code: The source code to check.
|
||||
|
||||
Returns:
|
||||
True if the code is in multi-file markdown format.
|
||||
|
||||
"""
|
||||
return code.strip().startswith("```python:")
|
||||
|
||||
def get_code_block_tag(self) -> str:
|
||||
"""Get the markdown code block tag for Python.
|
||||
|
||||
Returns:
|
||||
The string 'python' used in markdown code blocks.
|
||||
|
||||
"""
|
||||
return "python"
|
||||
|
||||
def split_markdown_code(self, markdown: str) -> dict[str, str]:
|
||||
"""Split markdown into filepath -> code dict.
|
||||
|
||||
Parses markdown with ```python:filepath blocks and returns
|
||||
a dictionary mapping file paths to their code content.
|
||||
|
||||
Args:
|
||||
markdown: The markdown text containing code blocks.
|
||||
|
||||
Returns:
|
||||
A dictionary mapping file paths to code content.
|
||||
|
||||
"""
|
||||
return _split_markdown_code(markdown, language="python")
|
||||
|
||||
def group_code(self, file_to_code: dict[str, str]) -> str:
|
||||
"""Combine code files into markdown format.
|
||||
|
||||
Args:
|
||||
file_to_code: A dictionary mapping file paths to code content.
|
||||
|
||||
Returns:
|
||||
Markdown-formatted string with ```python:filepath blocks.
|
||||
|
||||
"""
|
||||
blocks = []
|
||||
for file_path, code in file_to_code.items():
|
||||
# Ensure code ends with newline before closing ```
|
||||
normalized = code if code.endswith("\n") else code + "\n"
|
||||
blocks.append(f"```python:{file_path}\n{normalized}```")
|
||||
return "\n".join(blocks)
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
"""Python code syntax validation.
|
||||
|
||||
This module provides a validator that uses libcst for Python syntax validation.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import libcst as cst
|
||||
|
||||
from aiservice.common.cst_utils import parse_module_to_cst
|
||||
|
||||
|
||||
class PythonValidator:
|
||||
"""Validator for Python code syntax using libcst."""
|
||||
|
||||
def validate_syntax(self, code: str) -> tuple[bool, str | None]:
|
||||
"""Validate Python syntax using libcst.
|
||||
|
||||
Args:
|
||||
code: The Python code to validate.
|
||||
|
||||
Returns:
|
||||
A tuple of (is_valid, error_message).
|
||||
- is_valid: True if the code is syntactically valid Python.
|
||||
- error_message: None if valid, otherwise the parse error message.
|
||||
|
||||
"""
|
||||
try:
|
||||
parse_module_to_cst(code)
|
||||
return True, None
|
||||
except cst.ParserSyntaxError as e:
|
||||
return False, str(e)
|
||||
except Exception as e:
|
||||
# Catch any other parsing errors
|
||||
return False, f"Parse error: {e}"
|
||||
|
|
@ -53,7 +53,7 @@ class OptimizeErrorResponseSchema(Schema):
|
|||
|
||||
|
||||
##########################################################################################
|
||||
# BaseOptimizerContext #
|
||||
# BaseOptimizerContext [PYTHON ONLY] #
|
||||
##########################################################################################
|
||||
class BaseOptimizerContext:
|
||||
def __init__(self, base_system_prompt: str, base_user_prompt: str, source_code: str) -> None:
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ from pydantic import ValidationError
|
|||
|
||||
from aiservice.common.cst_utils import parse_module_to_cst
|
||||
from aiservice.common.markdown_utils import wrap_code_in_markdown
|
||||
from aiservice.validators.javascript_validator import validate_javascript_syntax
|
||||
from optimizer.context_utils.context_helpers import (
|
||||
group_code,
|
||||
is_markdown_structure_changed,
|
||||
|
|
@ -90,10 +91,9 @@ class BaseRefinerContext:
|
|||
if stripped_code == self.data.optimized_source_code.strip():
|
||||
return False
|
||||
|
||||
# For JavaScript/TypeScript, skip Python-specific syntax validation
|
||||
if self.data.language in ("javascript", "typescript"):
|
||||
# Basic validation: check it's not empty and has some code-like content
|
||||
return len(stripped_code) > 10 and any(c in stripped_code for c in "{}();")
|
||||
valid, _ = validate_javascript_syntax(stripped_code)
|
||||
return bool(valid)
|
||||
|
||||
try:
|
||||
parse_module_to_cst(new_refined_code)
|
||||
|
|
@ -153,12 +153,10 @@ class SingleRefinerContext(BaseRefinerContext):
|
|||
|
||||
def validate_code_syntax(self, code: str) -> None:
|
||||
"""Validate code syntax based on language."""
|
||||
# For JavaScript/TypeScript, skip Python-specific validation
|
||||
if self.data.language in ("javascript", "typescript"):
|
||||
# Basic validation: non-empty code
|
||||
if not code.strip():
|
||||
msg = "Empty code"
|
||||
raise ValueError(msg)
|
||||
valid, _ = validate_javascript_syntax(code)
|
||||
if not valid:
|
||||
raise ValueError("Invalid JavaScript syntax")
|
||||
return
|
||||
|
||||
# Python validation using libcst
|
||||
|
|
@ -199,10 +197,9 @@ class MultiRefinerContext(BaseRefinerContext):
|
|||
"""Validate code syntax based on language."""
|
||||
# For JavaScript/TypeScript, skip Python-specific validation
|
||||
if self.data.language in ("javascript", "typescript"):
|
||||
# Basic validation: non-empty code
|
||||
if not code.strip():
|
||||
msg = "Empty code"
|
||||
raise ValueError(msg)
|
||||
valid, _ = validate_javascript_syntax(code)
|
||||
if not valid:
|
||||
raise ValueError("Invalid JavaScript syntax")
|
||||
return
|
||||
|
||||
# Python validation using libcst
|
||||
|
|
|
|||
|
|
@ -287,13 +287,8 @@ async def optimize(
|
|||
request: AuthenticatedRequest, data: OptimizeSchema
|
||||
) -> tuple[int, OptimizeResponseSchema | OptimizeErrorResponseSchema]:
|
||||
# Route based on language
|
||||
logging.warning(f"[OPTIMIZE DEBUG] Received request with language='{data.language}' (type: {type(data.language)})")
|
||||
if data.language in ("javascript", "typescript"):
|
||||
logging.warning("[OPTIMIZE DEBUG] Routing to optimize_javascript")
|
||||
return await optimize_javascript(request, data)
|
||||
|
||||
# Default: Python optimization
|
||||
logging.warning("[OPTIMIZE DEBUG] Routing to optimize_python")
|
||||
return await optimize_python(request, data)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
"""Tests for the languages module."""
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
"""Tests for the language registry and language implementations."""
|
||||
|
||||
import pytest
|
||||
|
||||
from languages import (
|
||||
UnsupportedLanguageError,
|
||||
get_language,
|
||||
get_supported_languages,
|
||||
is_language_supported,
|
||||
)
|
||||
from languages.base import CodeValidator, LanguageSupport
|
||||
|
||||
|
||||
class TestLanguageRegistry:
|
||||
"""Tests for the language registry."""
|
||||
|
||||
def test_get_supported_languages_returns_all_registered(self):
|
||||
"""Test that all registered languages are returned."""
|
||||
languages = get_supported_languages()
|
||||
assert "python" in languages
|
||||
assert "javascript" in languages
|
||||
assert "typescript" in languages
|
||||
|
||||
def test_is_language_supported_for_registered_languages(self):
|
||||
"""Test is_language_supported for registered languages."""
|
||||
assert is_language_supported("python")
|
||||
assert is_language_supported("javascript")
|
||||
assert is_language_supported("typescript")
|
||||
|
||||
def test_is_language_supported_for_aliases(self):
|
||||
"""Test is_language_supported for language aliases."""
|
||||
assert is_language_supported("js")
|
||||
assert is_language_supported("ts")
|
||||
|
||||
def test_is_language_supported_false_for_unknown(self):
|
||||
"""Test is_language_supported returns False for unknown languages."""
|
||||
assert not is_language_supported("ruby")
|
||||
assert not is_language_supported("go")
|
||||
|
||||
def test_get_language_returns_instance(self):
|
||||
"""Test get_language returns an instance of the language class."""
|
||||
py = get_language("python")
|
||||
assert py is not None
|
||||
assert py.language == "python"
|
||||
|
||||
def test_get_language_with_alias(self):
|
||||
"""Test get_language works with aliases."""
|
||||
js = get_language("js")
|
||||
assert js.language == "javascript"
|
||||
|
||||
ts = get_language("ts")
|
||||
assert ts.language == "typescript"
|
||||
|
||||
def test_get_language_case_insensitive(self):
|
||||
"""Test get_language is case insensitive."""
|
||||
py1 = get_language("Python")
|
||||
py2 = get_language("PYTHON")
|
||||
py3 = get_language("python")
|
||||
assert py1.language == py2.language == py3.language == "python"
|
||||
|
||||
def test_get_language_raises_for_unknown(self):
|
||||
"""Test get_language raises UnsupportedLanguageError for unknown languages."""
|
||||
with pytest.raises(UnsupportedLanguageError) as exc_info:
|
||||
get_language("ruby")
|
||||
assert "ruby" in str(exc_info.value)
|
||||
assert "Unsupported language" in str(exc_info.value)
|
||||
|
||||
|
||||
class TestPythonLanguage:
|
||||
"""Tests for the Python language implementation."""
|
||||
|
||||
@pytest.fixture
|
||||
def python_lang(self):
|
||||
"""Get Python language instance."""
|
||||
return get_language("python")
|
||||
|
||||
def test_language_property(self, python_lang):
|
||||
"""Test language property returns 'python'."""
|
||||
assert python_lang.language == "python"
|
||||
|
||||
def test_get_code_block_tag(self, python_lang):
|
||||
"""Test get_code_block_tag returns 'python'."""
|
||||
assert python_lang.get_code_block_tag() == "python"
|
||||
|
||||
def test_get_validator_returns_validator(self, python_lang):
|
||||
"""Test get_validator returns a CodeValidator."""
|
||||
validator = python_lang.get_validator()
|
||||
assert isinstance(validator, CodeValidator)
|
||||
|
||||
def test_validator_valid_python(self, python_lang):
|
||||
"""Test validator accepts valid Python code."""
|
||||
validator = python_lang.get_validator()
|
||||
is_valid, error = validator.validate_syntax("def foo():\n return 42")
|
||||
assert is_valid is True
|
||||
assert error is None
|
||||
|
||||
def test_validator_invalid_python(self, python_lang):
|
||||
"""Test validator rejects invalid Python code."""
|
||||
validator = python_lang.get_validator()
|
||||
is_valid, error = validator.validate_syntax("def foo( return 42")
|
||||
assert is_valid is False
|
||||
assert error is not None
|
||||
|
||||
def test_is_multi_context_false_for_plain_code(self, python_lang):
|
||||
"""Test is_multi_context returns False for plain Python code."""
|
||||
assert not python_lang.is_multi_context("def foo(): pass")
|
||||
assert not python_lang.is_multi_context("```python\ndef foo(): pass\n```")
|
||||
|
||||
def test_is_multi_context_true_for_markdown_with_path(self, python_lang):
|
||||
"""Test is_multi_context returns True for markdown with filepath."""
|
||||
code = "```python:test.py\ndef foo(): pass\n```"
|
||||
assert python_lang.is_multi_context(code)
|
||||
|
||||
def test_split_markdown_code(self, python_lang):
|
||||
"""Test split_markdown_code parses markdown correctly."""
|
||||
markdown = """```python:file1.py
|
||||
def foo():
|
||||
pass
|
||||
```
|
||||
|
||||
```python:file2.py
|
||||
def bar():
|
||||
pass
|
||||
```"""
|
||||
result = python_lang.split_markdown_code(markdown)
|
||||
assert "file1.py" in result
|
||||
assert "file2.py" in result
|
||||
assert "def foo():" in result["file1.py"]
|
||||
assert "def bar():" in result["file2.py"]
|
||||
|
||||
def test_group_code(self, python_lang):
|
||||
"""Test group_code formats code correctly."""
|
||||
file_to_code = {
|
||||
"file1.py": "def foo():\n pass",
|
||||
"file2.py": "def bar():\n pass",
|
||||
}
|
||||
result = python_lang.group_code(file_to_code)
|
||||
assert "```python:file1.py" in result
|
||||
assert "```python:file2.py" in result
|
||||
assert "def foo():" in result
|
||||
assert "def bar():" in result
|
||||
|
||||
|
||||
class TestJavaScriptLanguage:
|
||||
"""Tests for the JavaScript language implementation."""
|
||||
|
||||
@pytest.fixture
|
||||
def js_lang(self):
|
||||
"""Get JavaScript language instance."""
|
||||
return get_language("javascript")
|
||||
|
||||
def test_language_property(self, js_lang):
|
||||
"""Test language property returns 'javascript'."""
|
||||
assert js_lang.language == "javascript"
|
||||
|
||||
def test_get_code_block_tag(self, js_lang):
|
||||
"""Test get_code_block_tag returns 'javascript'."""
|
||||
assert js_lang.get_code_block_tag() == "javascript"
|
||||
|
||||
def test_get_validator_returns_validator(self, js_lang):
|
||||
"""Test get_validator returns a CodeValidator."""
|
||||
validator = js_lang.get_validator()
|
||||
assert isinstance(validator, CodeValidator)
|
||||
|
||||
def test_is_multi_context_false_for_plain_code(self, js_lang):
|
||||
"""Test is_multi_context returns False for plain JavaScript code."""
|
||||
assert not js_lang.is_multi_context("function foo() {}")
|
||||
assert not js_lang.is_multi_context("```javascript\nfunction foo() {}\n```")
|
||||
|
||||
def test_is_multi_context_true_for_markdown_with_path(self, js_lang):
|
||||
"""Test is_multi_context returns True for markdown with filepath."""
|
||||
code = "```javascript:test.js\nfunction foo() {}\n```"
|
||||
assert js_lang.is_multi_context(code)
|
||||
|
||||
code_short = "```js:test.js\nfunction foo() {}\n```"
|
||||
assert js_lang.is_multi_context(code_short)
|
||||
|
||||
def test_group_code(self, js_lang):
|
||||
"""Test group_code formats code correctly."""
|
||||
file_to_code = {
|
||||
"file1.js": "function foo() {}",
|
||||
"file2.js": "function bar() {}",
|
||||
}
|
||||
result = js_lang.group_code(file_to_code)
|
||||
assert "```javascript:file1.js" in result
|
||||
assert "```javascript:file2.js" in result
|
||||
|
||||
|
||||
class TestTypeScriptLanguage:
|
||||
"""Tests for the TypeScript language implementation."""
|
||||
|
||||
@pytest.fixture
|
||||
def ts_lang(self):
|
||||
"""Get TypeScript language instance."""
|
||||
return get_language("typescript")
|
||||
|
||||
def test_language_property(self, ts_lang):
|
||||
"""Test language property returns 'typescript'."""
|
||||
assert ts_lang.language == "typescript"
|
||||
|
||||
def test_get_code_block_tag(self, ts_lang):
|
||||
"""Test get_code_block_tag returns 'typescript'."""
|
||||
assert ts_lang.get_code_block_tag() == "typescript"
|
||||
|
||||
def test_is_multi_context_true_for_markdown_with_path(self, ts_lang):
|
||||
"""Test is_multi_context returns True for markdown with filepath."""
|
||||
code = "```typescript:test.ts\nfunction foo(): void {}\n```"
|
||||
assert ts_lang.is_multi_context(code)
|
||||
|
||||
code_short = "```ts:test.ts\nfunction foo(): void {}\n```"
|
||||
assert ts_lang.is_multi_context(code_short)
|
||||
|
||||
def test_group_code(self, ts_lang):
|
||||
"""Test group_code formats code correctly."""
|
||||
file_to_code = {"file1.ts": "function foo(): void {}"}
|
||||
result = ts_lang.group_code(file_to_code)
|
||||
assert "```typescript:file1.ts" in result
|
||||
|
||||
|
||||
class TestLanguageProtocolCompliance:
|
||||
"""Tests to verify language implementations satisfy the protocols."""
|
||||
|
||||
@pytest.mark.parametrize("lang_id", ["python", "javascript", "typescript"])
|
||||
def test_language_satisfies_protocol(self, lang_id):
|
||||
"""Test that each language satisfies the LanguageSupport protocol."""
|
||||
lang = get_language(lang_id)
|
||||
assert isinstance(lang, LanguageSupport)
|
||||
|
||||
# Verify all protocol methods exist and return expected types
|
||||
assert isinstance(lang.language, str)
|
||||
assert isinstance(lang.get_code_block_tag(), str)
|
||||
assert isinstance(lang.get_validator(), CodeValidator)
|
||||
assert isinstance(lang.is_multi_context("test"), bool)
|
||||
assert isinstance(lang.split_markdown_code("test"), dict)
|
||||
assert isinstance(lang.group_code({"a.py": "code"}), str)
|
||||
|
||||
@pytest.mark.parametrize("lang_id", ["python", "javascript", "typescript"])
|
||||
def test_validator_satisfies_protocol(self, lang_id):
|
||||
"""Test that each validator satisfies the CodeValidator protocol."""
|
||||
lang = get_language(lang_id)
|
||||
validator = lang.get_validator()
|
||||
assert isinstance(validator, CodeValidator)
|
||||
|
||||
# Verify validate_syntax returns expected tuple
|
||||
result = validator.validate_syntax("test code")
|
||||
assert isinstance(result, tuple)
|
||||
assert len(result) == 2
|
||||
assert isinstance(result[0], bool)
|
||||
assert result[1] is None or isinstance(result[1], str)
|
||||
Loading…
Reference in a new issue