Merge branch 'main' into testgen-jit-iter

This commit is contained in:
Aseem Saxena 2026-02-25 02:27:41 +05:30 committed by GitHub
commit 14feee119f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -5,30 +5,109 @@ Uses Node.js for validation when available, with a basic regex fallback.
from __future__ import annotations
import logging
from functools import lru_cache
from typing import TYPE_CHECKING
import tree_sitter_javascript
import tree_sitter_typescript
from tree_sitter import Language, Parser
from aiservice.common.markdown_utils import split_markdown_code
if TYPE_CHECKING:
from tree_sitter import Node
js_parser = Parser(Language(tree_sitter_javascript.language()))
ts_parser = Parser(Language(tree_sitter_typescript.language_typescript()))
@lru_cache(maxsize=200)
def _validate(code: str, lang: str) -> bool:
parser = js_parser if lang == "js" else ts_parser
tree = parser.parse(code.encode("utf8"))
return not tree.root_node.has_error
def _find_error_location(code: str, lang: str) -> str | None:
"""Find the location of the first syntax error in the code."""
parser = js_parser if lang == "js" else ts_parser
tree = parser.parse(code.encode("utf8"))
if not tree.root_node.has_error:
return None
def find_error(node: Node) -> tuple[int, int] | None:
if node.type == "ERROR":
return node.start_point
for child in node.children:
result = find_error(child)
if result:
return result
return None
error_point = find_error(tree.root_node)
if error_point:
line, col = error_point
lines = code.split("\n")
if line < len(lines):
error_line = lines[line]
return f"line {line + 1}, col {col}: {error_line[:80]}"
return f"line {line + 1}, col {col}"
return "unknown location"
@lru_cache(maxsize=100)
def validate_javascript_syntax(code: str) -> tuple[bool, str | None]:
tree = js_parser.parse(bytes(code, "utf8"))
has_error = tree.root_node.has_error
if has_error:
return False, "Invalid syntax"
if code.strip().startswith("```"):
# markdown code block
file_to_code = split_markdown_code(code, "javascript")
if not file_to_code:
msg = f"No JavaScript code blocks found in markdown. Code starts with: {code[:100]!r}"
logging.warning(msg)
# Fall through to validate the raw code
else:
for filepath, _code in file_to_code.items():
valid = _validate(_code, "js")
if not valid:
error_loc = _find_error_location(_code, "js")
msg = f"Invalid JavaScript syntax in {filepath}: {error_loc}. Code snippet: {_code[:200]!r}"
logging.error(msg)
return False, f"Invalid syntax at {error_loc}"
return True, None
valid = _validate(code, "js")
if not valid:
error_loc = _find_error_location(code, "js")
msg = f"Invalid JavaScript syntax: {error_loc}. Code snippet: {code[:200]!r}"
logging.error(msg)
return False, f"Invalid syntax at {error_loc}"
return True, None
@lru_cache(maxsize=100)
def validate_typescript_syntax(code: str) -> tuple[bool, str | None]:
tree = ts_parser.parse(bytes(code, "utf8"))
has_error = tree.root_node.has_error
if has_error:
return False, "Invalid syntax"
if code.strip().startswith("```"):
# markdown code block
file_to_code = split_markdown_code(code, "typescript")
if not file_to_code:
msg = f"No TypeScript code blocks found in markdown. Code starts with: {code[:100]!r}"
logging.warning(msg)
# Fall through to validate the raw code
else:
for filepath, _code in file_to_code.items():
valid = _validate(_code, "ts")
if not valid:
error_loc = _find_error_location(_code, "ts")
msg = f"Invalid TypeScript syntax in {filepath}: {error_loc}. Code snippet: {_code[:200]!r}"
logging.error(msg)
return False, f"Invalid syntax at {error_loc}"
return True, None
valid = _validate(code, "ts")
if not valid:
error_loc = _find_error_location(code, "ts")
msg = f"Invalid TypeScript syntax: {error_loc}. Code snippet: {code[:200]!r}"
logging.error(msg)
return False, f"Invalid syntax at {error_loc}"
return True, None