Files
Open_Ultra_SAST/src/openultrasast/semantic/extra.py
T
Marius CiepluchandClaude Opus 5 6b58c81ba0 feat(learning-harness): TypeScript and TSX rows parse under the semantic extra
Task 1.4. The optional extra gains the TypeScript grammar wheel, which ships two
grammars: a file with JSX needs the JSX-aware one and plain TypeScript needs the
other, so the parser picks by file suffix while the parsed file keeps the
language it was given. The walker already treated TypeScript as JavaScript, so
nothing else changes.

Eighteen agent-vfc rows and every TypeScript absence row were counted as
unsupported before this and could not be scored at all. They now parse on both
sides. The core install stays zero-dependency and the extra-free suite still
skips these tests.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
2026-09-06 09:17:01 +02:00

54 lines
2.0 KiB
Python

"""Optional semantic extra: lazy grammar load. Never import wheels at package load."""
from __future__ import annotations
import importlib
import importlib.util
import os
from typing import Any
# language -> (wheel module, the module attribute that builds the grammar). TypeScript ships two grammars;
# `.tsx` needs the JSX-aware one and plain `.ts` needs the other, so the caller asks for the one it needs.
_GRAMMAR_MODULES = {
"python": ("tree_sitter_python", "language"),
"javascript": ("tree_sitter_javascript", "language"),
"typescript": ("tree_sitter_typescript", "language_typescript"),
"tsx": ("tree_sitter_typescript", "language_tsx"),
"c": ("tree_sitter_c", "language"),
"cpp": ("tree_sitter_cpp", "language"),
"java": ("tree_sitter_java", "language"),
}
_PROBE_ENV = "OPENULTRASAST_TREE_SITTER_PROBE"
_PROBE_OFF = frozenset({"0", "off", "false", "unavailable", "no"})
_PROBE_ON = frozenset({"1", "on", "true", "available", "yes"})
def has_semantic_extra() -> bool:
"""True when the parser runtime and at least one in-scope grammar are importable."""
flag = os.environ.get(_PROBE_ENV, "").strip().lower()
if flag in _PROBE_OFF:
return False
if importlib.util.find_spec("tree_sitter") is None:
return False
return any(importlib.util.find_spec(module) is not None for module, _ in _GRAMMAR_MODULES.values())
def grammar_for(language: str) -> Any | None:
"""Return a tree_sitter.Language for an in-scope language, or None. Never raises into the scan."""
flag = os.environ.get(_PROBE_ENV, "").strip().lower()
if flag in _PROBE_OFF:
return None
entry = _GRAMMAR_MODULES.get(language)
if entry is None or importlib.util.find_spec("tree_sitter") is None:
return None
module_name, attribute = entry
if importlib.util.find_spec(module_name) is None:
return None
try:
from tree_sitter import Language
module = importlib.import_module(module_name)
return Language(getattr(module, attribute)())
except Exception:
return None