mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 19:59:26 +00:00
src/openultrasast/source.py replaces the copies in semantic/functions.py, plane/tasks/repo_facts.py, learn/features.py, learn/excerpt.py and plane/tasks/verify.py. Two engines share one sentinel (<module>), one DECLARATION/KEYWORDS/RESERVED set and one alias map: the parser engine (ranges, enclosing, bounds, call_sites, callers_of, facts_for) for the scorer, the overlay and the hunter's annotations; the line-pattern engine (declared_functions, enclosing_at, function_span, function_bounds, the brace matcher) that labels, features, roles, excerpts and plane facts were built on. learn no longer imports plane.tasks. Frozen records that store the old sentinel are mapped on read (module_function). Gate: labels rebuilt before and after are identical, 7,921 rows, after sentinel normalisation (benchmarks/measurements/2026-10-13-source-module- label-diff/record.json). 490 targeted tests pass; 3,312 collect. Net: 657 lines deleted, 212 added. benchmarks/unseen keeps <global> for its own frozen manifests. Co-Authored-By: Claude Fable 5.1 <[email protected]>
60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
"""freeze.py resolves an advisory's file-only site to the function the fix changes (population v3, decision 2).
|
|
|
|
The resolver reads PHP text only; it must not be fooled by braces in strings, comments or inline HTML, and a line
|
|
outside every function is `<module>`."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
from pathlib import Path
|
|
|
|
SPEC = importlib.util.spec_from_file_location("freeze", Path(__file__).resolve().parents[1] / "benchmarks" / "independent" / "freeze.py")
|
|
freeze = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(freeze)
|
|
|
|
PHP = """<html>{ not code }</html>
|
|
<?php
|
|
// a comment with { brace
|
|
class Box
|
|
{
|
|
public function open($x)
|
|
{
|
|
$s = "}{ in a string";
|
|
return function ($y) { return $y; };
|
|
}
|
|
|
|
abstract protected function shape();
|
|
|
|
private static function &close() {
|
|
/* } */
|
|
return <<<EOT
|
|
} heredoc {
|
|
EOT;
|
|
}
|
|
}
|
|
$top = 1;
|
|
?>
|
|
<div>{</div>
|
|
<?php function helper() { return '#{'; }
|
|
"""
|
|
|
|
|
|
def test_named_functions_and_their_lines() -> None:
|
|
spans = {name: (first, last) for name, first, last in freeze.php_functions(PHP)}
|
|
assert spans == {"open": (6, 10), "close": (14, 19), "helper": (24, 24)}
|
|
|
|
|
|
def test_a_line_resolves_to_its_innermost_named_function_or_global() -> None:
|
|
spans = freeze.php_functions(PHP)
|
|
assert freeze.enclosing(spans, 9) == "open" # inside the closure: the named function owns it
|
|
assert freeze.enclosing(spans, 17) == "close"
|
|
assert freeze.enclosing(spans, 21) == "<module>"
|
|
assert freeze.enclosing(spans, 1) == "<module>"
|
|
|
|
|
|
def test_an_insertion_after_a_closing_brace_is_outside_the_function() -> None:
|
|
spans = freeze.php_functions(PHP)
|
|
assert freeze.enclosing(spans, 10) == "open" # a changed line on the closing brace
|
|
assert freeze.enclosing(spans, 10, inserted=True) == "<module>" # new code that follows it
|
|
assert freeze.enclosing(spans, 8, inserted=True) == "open"
|