Add CLI and services modules
Some checks failed
CI / lint (push) Has been cancelled
CI / typecheck (push) Has been cancelled
CI / test (push) Has been cancelled

This commit is contained in:
2026-01-30 18:58:59 +00:00
parent bdf70080fd
commit 7fa1a39adf

View File

@@ -0,0 +1,177 @@
"""Syntax verification utilities for CodeXchange CLI."""
import ast
import re
import subprocess
from typing import Tuple
from codexchange.models import Language
def check_python_syntax(code: str) -> Tuple[bool, list[str]]:
"""Check Python syntax using ast.parse.
Args:
code: Python code to check.
Returns:
Tuple of (is_valid, error_message).
"""
try:
ast.parse(code)
return True, []
except SyntaxError as e:
return False, [f"Syntax error at line {e.lineno}: {e.msg}"]
def check_typescript_syntax(code: str) -> Tuple[bool, list[str]]:
"""Check TypeScript syntax using tsc --noEmit.
Args:
code: TypeScript code to check.
Returns:
Tuple of (is_valid, list of warnings/errors).
"""
import tempfile
import os
warnings = []
with tempfile.NamedTemporaryFile(mode="w", suffix=".ts", delete=False) as f:
f.write(code)
temp_file = f.name
try:
result = subprocess.run(
["npx", "tsc", "--noEmit", "--skipLibCheck", temp_file],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
for line in result.stderr.split("\n"):
line = line.strip()
if line and "error" in line.lower():
warnings.append(line)
if not warnings:
warnings = result.stderr.strip().split("\n")
warnings = [w for w in warnings if w.strip()]
except FileNotFoundError:
warnings.append("TypeScript compiler (tsc) not found. Install Node.js and TypeScript.")
except subprocess.TimeoutExpired:
warnings.append("TypeScript compilation timed out.")
except Exception as e:
warnings.append(f"TypeScript check failed: {str(e)}")
finally:
os.unlink(temp_file)
return len(warnings) == 0, warnings
def check_javascript_syntax(code: str) -> Tuple[bool, list[str]]:
"""Check JavaScript syntax using ESLint or basic parsing.
Args:
code: JavaScript code to check.
Returns:
Tuple of (is_valid, list of warnings/errors).
"""
import tempfile
import os
warnings = []
with tempfile.NamedTemporaryFile(mode="w", suffix=".js", delete=False) as f:
f.write(code)
temp_file = f.name
try:
result = subprocess.run(
["npx", "eslint", "--format", "compact", temp_file],
capture_output=True,
text=True,
timeout=30
)
if result.returncode != 0:
for line in result.stderr.split("\n"):
line = line.strip()
if line:
warnings.append(line)
output = result.stdout.strip()
if output:
warnings.extend(output.split("\n"))
except FileNotFoundError:
warnings.append("ESLint not found. Install Node.js and ESLint for JavaScript validation.")
except subprocess.TimeoutExpired:
warnings.append("ESLint check timed out.")
except Exception as e:
warnings.append(f"JavaScript check failed: {str(e)}")
finally:
os.unlink(temp_file)
return len(warnings) == 0, warnings
def check_java_syntax(code: str) -> Tuple[bool, list[str]]:
"""Check Java syntax (basic validation).
Args:
code: Java code to check.
Returns:
Tuple of (is_valid, list of warnings/errors).
"""
warnings = []
if not code.strip():
return False, ["Empty Java file"]
class_name_pattern = r"public\s+class\s+(\w+)"
matches = re.findall(class_name_pattern, code)
if not matches:
warnings.append("No public class found in Java file")
brace_count = code.count("{") - code.count("}")
if brace_count != 0:
warnings.append("Mismatched braces in Java file")
if code.count("(") != code.count(")"):
warnings.append("Mismatched parentheses in Java file")
return len(warnings) == 0, warnings
def verify_syntax(code: str, language: Language) -> Tuple[bool, list[str]]:
"""Verify syntax for the given language.
Args:
code: Source code to verify.
language: Programming language of the code.
Returns:
Tuple of (is_valid, list of warnings/errors).
"""
if not code or not code.strip():
return False, ["Empty code input"]
checkers = {
Language.PYTHON: check_python_syntax,
Language.TYPESCRIPT: check_typescript_syntax,
Language.JAVASCRIPT: check_javascript_syntax,
Language.JAVA: check_java_syntax,
}
checker = checkers.get(language)
if not checker:
return True, []
return checker(code)